diff --git a/.github/actions/setup-lean/action.yml b/.github/actions/setup-lean/action.yml index 60bd00068..d093a555f 100644 --- a/.github/actions/setup-lean/action.yml +++ b/.github/actions/setup-lean/action.yml @@ -221,6 +221,11 @@ runs: --path ".lake/build" \ --fallback-key "${{ steps.persistence.outputs.build_main_fallback_sticky_key }}" + - name: Prune stale sticky Lake packages + if: steps.persistence.outputs.use_sticky_disks == 'true' + shell: bash + run: python3 scripts/prune_lake_cache.py --packages-only + - name: Refresh Lake dependency state on partial cache hit if: steps.persistence.outputs.use_sticky_disks != 'true' && steps.cache-lake.outputs.cache-hit != 'true' shell: bash diff --git a/.github/actions/setup-solc/action.yml b/.github/actions/setup-solc/action.yml index a52b42e9b..e29fe6fcc 100644 --- a/.github/actions/setup-solc/action.yml +++ b/.github/actions/setup-solc/action.yml @@ -8,17 +8,41 @@ runs: id: cache-solc uses: actions/cache@v5 with: - path: /usr/local/bin/solc + path: .cache/solc/${{ env.SOLC_VERSION }} key: solc-${{ env.SOLC_VERSION }} - - name: Install solc - if: steps.cache-solc.outputs.cache-hit != 'true' + - name: Install or repair solc shell: bash run: | - curl -sSfL "$SOLC_URL" -o solc - echo "${SOLC_SHA256} solc" | sha256sum -c - - sudo mv solc /usr/local/bin/solc - sudo chmod +x /usr/local/bin/solc + solc_bin_dir="$PWD/.cache/solc/${SOLC_VERSION}" + solc_path="${solc_bin_dir}/solc" + mkdir -p "$solc_bin_dir" + echo "$solc_bin_dir" >> "$GITHUB_PATH" + + if [ -x "$solc_path" ] && "$solc_path" --version | grep -q "$SOLC_VERSION"; then + exit 0 + fi + + for delay in 0 5 15; do + if [ "$delay" -gt 0 ]; then + echo "::warning::solc install failed; retrying in ${delay}s" + sleep "$delay" + fi + + rm -f solc + if \ + curl -sSfL --retry 3 --retry-delay 5 "$SOLC_URL" -o solc && \ + echo "${SOLC_SHA256} solc" | sha256sum -c - && \ + mv solc "$solc_path" && \ + chmod +x "$solc_path" && \ + "$solc_path" --version | grep -q "$SOLC_VERSION" + then + exit 0 + fi + done + + echo "::error::Unable to install solc ${SOLC_VERSION}" + exit 1 - name: Verify solc shell: bash diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index db34d7890..85b418787 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -202,7 +202,7 @@ jobs: checks: runs-on: [self-hosted, linux, ARM64, dgx-spark, verity, fastlane] - timeout-minutes: 5 + timeout-minutes: 10 permissions: contents: write steps: diff --git a/Compiler.lean b/Compiler.lean index 8854c2563..119d4707b 100644 --- a/Compiler.lean +++ b/Compiler.lean @@ -29,7 +29,6 @@ import Compiler.Keccak.SpongeProperties import Compiler.Proofs.KeccakBound import Compiler.Proofs.MappingSlot import Compiler.Proofs.IRGeneration.Expr -import Compiler.Proofs.IRGeneration.IRInterpreter import Compiler.Proofs.IRGeneration.SupportedFragment import Compiler.Proofs.IRGeneration.Contract import Compiler.Proofs.IRGeneration.Dispatch @@ -39,15 +38,5 @@ import Compiler.Proofs.IRGeneration.ParamLoading import Compiler.Proofs.IRGeneration.SupportedSpec import Compiler.Proofs.IRGeneration.SourceSemantics import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanAdapter -import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeLemmas -import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeTest -import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins -import Compiler.Proofs.YulGeneration.Codegen -import Compiler.Proofs.YulGeneration.Equivalence -import Compiler.Proofs.YulGeneration.Lemmas import Compiler.Proofs.YulGeneration.PatchRulesProofs -import Compiler.Proofs.YulGeneration.Preservation -import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics -import Compiler.Proofs.YulGeneration.StatementEquivalence import Compiler.Proofs.EndToEnd -import Compiler.Proofs.ArithmeticProfile diff --git a/Compiler/CompilationModel/ExpressionCompile.lean b/Compiler/CompilationModel/ExpressionCompile.lean index af4b60a4b..bbe38f1a7 100644 --- a/Compiler/CompilationModel/ExpressionCompile.lean +++ b/Compiler/CompilationModel/ExpressionCompile.lean @@ -21,7 +21,8 @@ def yulNegatedBinOp (op : String) (a b : YulExpr) : YulExpr := def yulToBool (e : YulExpr) : YulExpr := YulExpr.call "iszero" [YulExpr.call "iszero" [e]] -private def compileMappingSlotRead (fields : List Field) (field : String) (keyExpr : YulExpr) +-- Exposed so proof modules can name the exact mapping-read lowering shape. +def compileMappingSlotRead (fields : List Field) (field : String) (keyExpr : YulExpr) (label : String) (wordOffset : Nat := 0) : Except String YulExpr := if !isMapping fields field then throw s!"Compilation error: field '{field}' is not a mapping" @@ -33,7 +34,8 @@ private def compileMappingSlotRead (fields : List Field) (field : String) (keyEx pure (YulExpr.call "sload" [finalSlot]) | none => throw s!"Compilation error: unknown mapping field '{field}' in {label}" -private def compileMappingSlotChain (baseSlot : YulExpr) (keys : List YulExpr) : YulExpr := +-- Exposed so proof modules can name the exact nested mapping-chain lowering shape. +def compileMappingSlotChain (baseSlot : YulExpr) (keys : List YulExpr) : YulExpr := keys.foldl (fun slotExpr keyExpr => YulExpr.call "mappingSlot" [slotExpr, keyExpr]) baseSlot -- Compile expression to Yul (using mutual recursion for lists) diff --git a/Compiler/Proofs/ArithmeticProfile.lean b/Compiler/Proofs/ArithmeticProfile.lean index 9ffd8660a..985f4c27d 100644 --- a/Compiler/Proofs/ArithmeticProfile.lean +++ b/Compiler/Proofs/ArithmeticProfile.lean @@ -7,26 +7,22 @@ This file serves as the single formal reference for arithmetic behavior: - Proves wrapping is consistent across EDSL and compiler layers - - Proves EVMYulLean bridge agreement for pure builtins + - States compiler pure-builtin facts directly against EVMYulLean - Documents the checked (safe) arithmetic alternative at EDSL level - - Establishes that all backend profiles share identical arithmetic semantics + - Keeps legacy/native bridge comparisons out of the public profile surface Run: lake build Compiler.Proofs.ArithmeticProfile -/ import Compiler.Constants -import Compiler.Proofs.IRGeneration.IRStorageWord -import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanAdapter -import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeLemmas +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanPureBuiltinLemmas import Verity.Core.Uint256 import EvmYul.UInt256 namespace Compiler.Proofs.ArithmeticProfile open Compiler.Constants (evmModulus) -open Compiler.Proofs.IRGeneration (IRStorageWord IRStorageSlot) -open Compiler.Proofs.YulGeneration (evalBuiltinCall) open Compiler.Proofs.YulGeneration.Backends (evalPureBuiltinViaEvmYulLean) -- ============================================================================ @@ -44,130 +40,117 @@ theorem evmyullean_size_eq_verity_modulus : -- § 2. Wrapping semantics: compiler builtins are total and wrapping -- ============================================================================ --- Dummy state parameters (arithmetic builtins are state-independent). -private def s : IRStorageSlot → IRStorageWord := fun _ => 0 -private def sender : Nat := 0 -private def sel : Nat := 0 -private def cd : List Nat := [] - /-- Addition wraps: (a + b) mod 2^256. -/ theorem add_wraps (a b : Nat) : - evalBuiltinCall s sender sel cd "add" [a, b] = some ((a + b) % evmModulus) := by - simp [evalBuiltinCall, Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + evalPureBuiltinViaEvmYulLean "add" [a, b] = + some ((a + b) % evmModulus) := by + simp /-- Subtraction wraps: (2^256 + a - b) mod 2^256. -/ theorem sub_wraps (a b : Nat) : - evalBuiltinCall s sender sel cd "sub" [a, b] = + evalPureBuiltinViaEvmYulLean "sub" [a, b] = some ((evmModulus + a % evmModulus - b % evmModulus) % evmModulus) := by - simp [evalBuiltinCall, Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + simp /-- Multiplication wraps: (a * b) mod 2^256. -/ theorem mul_wraps (a b : Nat) : - evalBuiltinCall s sender sel cd "mul" [a, b] = some ((a * b) % evmModulus) := by - simp [evalBuiltinCall, Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + evalPureBuiltinViaEvmYulLean "mul" [a, b] = + some ((a * b) % evmModulus) := by + simp /-- Division by zero returns 0. -/ theorem div_by_zero (a : Nat) : - evalBuiltinCall s sender sel cd "div" [a, 0] = some 0 := by - simp [evalBuiltinCall, Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + evalPureBuiltinViaEvmYulLean "div" [a, 0] = some 0 := by + simp /-- Modulo by zero returns 0. -/ theorem mod_by_zero (a : Nat) : - evalBuiltinCall s sender sel cd "mod" [a, 0] = some 0 := by - simp [evalBuiltinCall, Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + evalPureBuiltinViaEvmYulLean "mod" [a, 0] = some 0 := by + simp -- ============================================================================ --- § 3. EVMYulLean bridge agreement for pure arithmetic +-- § 3. EVMYulLean pure-builtin facts -- ============================================================================ --- Arithmetic bridging is now universally proved for add/sub/mul/div/mod. --- Bitwise `and`/`or`/`xor` plus the shift family now also have direct symbolic bridge lemmas. --- `not` still retains concrete bridge coverage here. +-- The theorem names retain the historical `_bridge` suffix for downstream +-- compatibility, but their semantic authority is the native EVMYulLean +-- evaluator rather than the legacy Verity Yul oracle. -/-- Universal bridge theorem for addition. -/ +/-- Native evaluator theorem for addition. -/ theorem add_bridge (a b : Nat) : - evalBuiltinCall s sender sel cd "add" [a, b] = - evalPureBuiltinViaEvmYulLean "add" [a, b] := by - exact Compiler.Proofs.YulGeneration.Backends.evalBuiltinCall_add_bridge - s sender sel cd a b + evalPureBuiltinViaEvmYulLean "add" [a, b] = + some ((a + b) % evmModulus) := + add_wraps a b -/-- Universal bridge theorem for subtraction. -/ +/-- Native evaluator theorem for subtraction. -/ theorem sub_bridge (a b : Nat) : - evalBuiltinCall s sender sel cd "sub" [a, b] = - evalPureBuiltinViaEvmYulLean "sub" [a, b] := by - exact Compiler.Proofs.YulGeneration.Backends.evalBuiltinCall_sub_bridge - s sender sel cd a b + evalPureBuiltinViaEvmYulLean "sub" [a, b] = + some ((evmModulus + a % evmModulus - b % evmModulus) % evmModulus) := + sub_wraps a b -/-- Universal bridge theorem for multiplication. -/ +/-- Native evaluator theorem for multiplication. -/ theorem mul_bridge (a b : Nat) : - evalBuiltinCall s sender sel cd "mul" [a, b] = - evalPureBuiltinViaEvmYulLean "mul" [a, b] := by - exact Compiler.Proofs.YulGeneration.Backends.evalBuiltinCall_mul_bridge - s sender sel cd a b + evalPureBuiltinViaEvmYulLean "mul" [a, b] = + some ((a * b) % evmModulus) := + mul_wraps a b -/-- Universal bridge theorem for division. -/ +/-- Native evaluator theorem for division. -/ theorem div_bridge (a b : Nat) : - evalBuiltinCall s sender sel cd "div" [a, b] = - evalPureBuiltinViaEvmYulLean "div" [a, b] := by - exact Compiler.Proofs.YulGeneration.Backends.evalBuiltinCall_div_bridge - s sender sel cd a b + evalPureBuiltinViaEvmYulLean "div" [a, b] = + some (if b % evmModulus = 0 then 0 else (a % evmModulus) / (b % evmModulus)) := by + simp -/-- Universal bridge theorem for modulo. -/ +/-- Native evaluator theorem for modulo. -/ theorem mod_bridge (a b : Nat) : - evalBuiltinCall s sender sel cd "mod" [a, b] = - evalPureBuiltinViaEvmYulLean "mod" [a, b] := by - exact Compiler.Proofs.YulGeneration.Backends.evalBuiltinCall_mod_bridge - s sender sel cd a b + evalPureBuiltinViaEvmYulLean "mod" [a, b] = + some (if b % evmModulus = 0 then 0 else + (a % evmModulus) % (b % evmModulus)) := by + simp -/-- Universal bridge theorem for bitwise and. -/ +/-- Native evaluator theorem for bitwise and. -/ theorem and_bridge (a b : Nat) : - evalBuiltinCall s sender sel cd "and" [a, b] = - evalPureBuiltinViaEvmYulLean "and" [a, b] := by - exact Compiler.Proofs.YulGeneration.Backends.evalBuiltinCall_and_bridge - s sender sel cd a b + evalPureBuiltinViaEvmYulLean "and" [a, b] = + some (EvmYul.UInt256.toNat + (EvmYul.UInt256.land (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b))) := by + rfl -/-- Universal bridge theorem for bitwise or. -/ +/-- Native evaluator theorem for bitwise or. -/ theorem or_bridge (a b : Nat) : - evalBuiltinCall s sender sel cd "or" [a, b] = - evalPureBuiltinViaEvmYulLean "or" [a, b] := by - exact Compiler.Proofs.YulGeneration.Backends.evalBuiltinCall_or_bridge - s sender sel cd a b + evalPureBuiltinViaEvmYulLean "or" [a, b] = + some (EvmYul.UInt256.toNat + (EvmYul.UInt256.lor (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b))) := by + rfl -/-- Universal bridge theorem for bitwise xor. -/ +/-- Native evaluator theorem for bitwise xor. -/ theorem xor_bridge (a b : Nat) : - evalBuiltinCall s sender sel cd "xor" [a, b] = - evalPureBuiltinViaEvmYulLean "xor" [a, b] := by - exact Compiler.Proofs.YulGeneration.Backends.evalBuiltinCall_xor_bridge - s sender sel cd a b + evalPureBuiltinViaEvmYulLean "xor" [a, b] = + some (EvmYul.UInt256.toNat + (EvmYul.UInt256.xor (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b))) := by + rfl -/-- Universal bridge theorem for shift-left. -/ +/-- Native evaluator theorem for shift-left. -/ theorem shl_bridge (shift value : Nat) : - evalBuiltinCall s sender sel cd "shl" [shift, value] = - evalPureBuiltinViaEvmYulLean "shl" [shift, value] := by - exact Compiler.Proofs.YulGeneration.Backends.evalBuiltinCall_shl_bridge - s sender sel cd shift value + evalPureBuiltinViaEvmYulLean "shl" [shift, value] = + some (EvmYul.UInt256.toNat + (EvmYul.UInt256.shiftLeft + (EvmYul.UInt256.ofNat value) (EvmYul.UInt256.ofNat shift))) := by + rfl -/-- Universal bridge theorem for shift-right. -/ +/-- Native evaluator theorem for shift-right. -/ theorem shr_bridge (shift value : Nat) : - evalBuiltinCall s sender sel cd "shr" [shift, value] = - evalPureBuiltinViaEvmYulLean "shr" [shift, value] := by - exact Compiler.Proofs.YulGeneration.Backends.evalBuiltinCall_shr_bridge - s sender sel cd shift value + evalPureBuiltinViaEvmYulLean "shr" [shift, value] = + some (EvmYul.UInt256.toNat + (EvmYul.UInt256.shiftRight + (EvmYul.UInt256.ofNat value) (EvmYul.UInt256.ofNat shift))) := by + rfl -- ============================================================================ -- § 4. Backend profile invariant -- ============================================================================ --- All backend profiles (semantic, solidity-parity-ordering, solidity-parity) --- use the same evalBuiltinCall function. The profiles differ only in Yul --- output shape (selector sorting, patch pass enablement), not arithmetic --- semantics. This is enforced structurally: there is a single evalBuiltinCall --- definition that all codepaths use. - -/-- The BuiltinBackend enum has exactly two variants. -/ -example : ∀ b : Compiler.Proofs.YulGeneration.BuiltinBackend, - b = .verity ∨ b = .evmYulLean := by - intro b; cases b <;> simp +-- Public arithmetic facts in this module are stated directly against +-- `evalPureBuiltinViaEvmYulLean`; legacy backend comparison lemmas remain in +-- the transition bridge modules, not as this profile's semantic authority. -- ============================================================================ -- § 5. Scope boundaries (what is NOT proved here) @@ -183,9 +166,8 @@ example : ∀ b : Compiler.Proofs.YulGeneration.BuiltinBackend, -- Cryptographic primitives: keccak256 is axiomatized (see AXIOMS.md). -- The mapping-slot derivation trusts the keccak FFI. -- --- Universal bridge equivalence: all pure arithmetic/comparison builtins plus --- bitwise and/or/xor and the shift family now have direct symbolic bridge lemmas --- in `Backends/EvmYulLeanBridgeLemmas.lean`. --- `not` still relies on concrete bridge coverage. +-- Legacy/native bridge equivalence: comparison lemmas are part of the +-- transition bridge modules. This profile intentionally exposes only native +-- evaluator facts. end Compiler.Proofs.ArithmeticProfile diff --git a/Compiler/Proofs/EndToEnd.lean b/Compiler/Proofs/EndToEnd.lean index 2116159fa..87adf347f 100644 --- a/Compiler/Proofs/EndToEnd.lean +++ b/Compiler/Proofs/EndToEnd.lean @@ -1,11 +1,12 @@ /- - Compiler.Proofs.EndToEnd: Composed Layers 2+3 End-to-End Theorem + Compiler.Proofs.EndToEnd: Composed Layers 2+3 Native End-to-End Theorem - Composes the existing Layer 2 (CompilationModel → IR) and Layer 3 (IR → Yul) + Composes the existing Layer 2 (CompilationModel -> IR) and native Layer 3 preservation theorems into a single end-to-end result: - For any CompilationModel, evaluating the compiled Yul via the proof semantics - produces the same result as the IR semantics. + For supported compiler output, native EVMYulLean runtime execution through + `EvmYul.Yul.callDispatcher` matches the IR semantics on the observable + result surface. This is the first step toward eliminating `interpretSpec` from the TCB (Issue #998). Once primitive-level EDSL ≡ compiled-Yul lemmas are proven, @@ -15,40 +16,33 @@ - Layer 2: `compile spec selectors = .ok irContract` `interpretIR irContract tx irState ≡ interpretSpec spec ...` (proven per-contract in Compiler/Proofs/IRGeneration/Expr.lean) - - Layer 3: `interpretIR irContract tx irState ≡ interpretYulFromIR irContract tx irState` - (proven generically in Compiler/Proofs/YulGeneration/Preservation.lean) + - Native Layer 3: `interpretIR irContract tx irState` matches + `interpretIRRuntimeNative fuel irContract tx irState observableSlots` + through the native harness over `EvmYul.Yul.callDispatcher`. - This file: compose them into a single theorem statement. - **EVMYulLean note (Phase 4)**: This file now exposes both the historical - Verity-backed Yul target (`interpretYulFromIR`) and safe-body public wrappers - targeting `interpretYulRuntimeWithBackend .evmYulLean`. - The default Yul execution semantics (`interpretYulFromIR`, `interpretYulRuntime`) - are still defined in terms of `evalBuiltinCallWithBackend` which defaults to - the Verity backend. The EVMYulLean bridge is established in - `Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean`, proving - that for all 36 bridged builtins, the Verity backend agrees with EVMYulLean. - The Phase 4 retargeting module (`EvmYulLeanRetarget.lean`) composes these - per-builtin equivalences through expression evaluation and recursive - `BridgedTarget` statement execution. It also proves that the emitted runtime - wrapper satisfies that predicate, and executes equivalently under the - EVMYulLean backend, when the IR bodies it contains do. It also exposes a - lower-level Layer-3 theorem whose Yul side is - `interpretYulRuntimeWithBackend .evmYulLean` and whose body witnesses are - supplied by this file's public wrappers. Those wrappers derive raw external - function-body bridge witnesses from source-level `SupportedSpec`, - static-parameter, and `BridgedSafeStmts` witnesses where the public theorem - applies. + **EVMYulLean note (native transition)**: the active public native surface in + this file is `nativeResultsMatchOn`, `sourceResultMatchesNativeOn`, and the + concrete generated-dispatcher theorem family below them. The file-local + runtime seams compare IR execution directly with native + `EvmYul.Yul.callDispatcher` execution through + `Compiler.Proofs.YulGeneration.Backends.EvmYulLeanNativeHarness`. + +Historical EVMYulLean backend-fuel retargeting lemmas remain isolated outside +this public theorem spine; this file no longer exposes or composes EndToEnd +wrappers over that proof-interpreter target. Run: lake build Compiler.Proofs.EndToEnd -/ -import Compiler.Proofs.YulGeneration.Preservation -import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanRetarget import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBodyClosure import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanNativeHarness +import Compiler.Proofs.YulGeneration.RuntimeTypes import Compiler.Proofs.IRGeneration.Contract -import Compiler.Proofs.IRGeneration.Function +import Compiler.Proofs.IRGeneration.ContractShape +import Compiler.Proofs.IRGeneration.FunctionShape import Compiler.Proofs.IRGeneration.Expr +import Compiler.Proofs.IRGeneration.FunctionBody import Compiler.SimpleStorageNativeWitness namespace Compiler.Proofs.EndToEnd @@ -56,344 +50,1089 @@ namespace Compiler.Proofs.EndToEnd open Compiler open Compiler.Proofs.IRGeneration open Compiler.Proofs.YulGeneration +open Compiler.Proofs.YulGeneration.Backends /-! ## Native Runtime Result Surface -/ -/-- Result comparison surface for the native EVMYulLean harness. +/-- Observable result comparison surface for native EVMYulLean execution. -/ +abbrev nativeResultsMatchOn := + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn -The native harness can still fail closed during Verity-Yul-to-EVMYulLean -lowering, so the native-facing public theorem states both that native execution -returns a `YulResult` and that this result matches IR execution. -/ -def nativeResultsMatch - (ir : IRResult) - (native : Except Compiler.Proofs.YulGeneration.Backends.AdapterError YulResult) : +/-- Native EVMYulLean execution matches the IR semantics on the observable +result surface. -/ +private def nativeIRRuntimeMatchesIR + (fuel : Nat) + (contract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := - match native with - | .ok yul => Compiler.Proofs.YulGeneration.resultsMatch ir yul - | .error _ => False + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + fuel contract tx state observableSlots) -/-- Observable native result comparison for the current native bridge. +/-- Observable source-result comparison surface for native EVMYulLean execution. -The native EVMYulLean state bridge materializes only the storage slots supplied -by the caller. Until the generated-fragment bridge proves a complete storage -projection, native-facing theorems compare success, return value, events, and -the explicitly observable final-storage slots. -/ -def yulResultsAgreeOn - (observableSlots : List Nat) (left right : YulResult) : Prop := - left.success = right.success ∧ - left.returnValue = right.returnValue ∧ - (∀ slot, slot ∈ observableSlots → - left.finalStorage (IRStorageSlot.ofNat slot) = right.finalStorage (IRStorageSlot.ofNat slot)) ∧ - left.events = right.events - -/-- Observable result comparison surface for native EVMYulLean execution. -/ -def nativeResultsMatchOn +This is the public composition target for source-level compiler correctness: +the storage comparison is intentionally projected to `observableSlots`, matching +the native harness' materialized-storage boundary. -/ +def sourceResultMatchesNativeOn (observableSlots : List Nat) - (ir : IRResult) + (source : SourceSemantics.SourceContractResult) (native : Except Compiler.Proofs.YulGeneration.Backends.AdapterError YulResult) : Prop := match native with | .ok yul => - ir.success = yul.success ∧ - ir.returnValue = yul.returnValue ∧ + source.success = yul.success ∧ + source.returnValue = yul.returnValue ∧ (∀ slot, slot ∈ observableSlots → - ir.finalStorage (IRStorageSlot.ofNat slot) = yul.finalStorage (IRStorageSlot.ofNat slot)) ∧ - ir.events = yul.events + IRStorageWord.ofNat + (source.finalStorage (IRStorageSlot.ofNat slot).toNat) = + yul.finalStorage (IRStorageSlot.ofNat slot)) ∧ + source.events = yul.events | .error _ => False -theorem nativeResultsMatchOn_ok_of_resultsMatch_of_yulResultsAgreeOn - {observableSlots : List Nat} {ir : IRResult} {native oracle : YulResult} - (hLayer : Compiler.Proofs.YulGeneration.resultsMatch ir oracle) - (hNative : yulResultsAgreeOn observableSlots native oracle) : - nativeResultsMatchOn observableSlots ir (.ok native) := by - rcases hLayer with ⟨hsuccess, hreturnValue, hstorage, _hmappings, hevents⟩ - rcases hNative with ⟨hnativeSuccess, hnativeReturnValue, hnativeStorage, hnativeEvents⟩ - exact ⟨ - hsuccess.trans hnativeSuccess.symm, - hreturnValue.trans hnativeReturnValue.symm, - (by - intro slot hslot - exact (hstorage (IRStorageSlot.ofNat slot)).trans (hnativeStorage slot hslot).symm), - hevents.trans hnativeEvents.symm - ⟩ - -theorem yulResultsAgreeOn_of_resultsMatch_of_nativeResultsMatchOn - {observableSlots : List Nat} {ir : IRResult} {native oracle : YulResult} - (hOracle : Compiler.Proofs.YulGeneration.resultsMatch ir oracle) - (hNative : nativeResultsMatchOn observableSlots ir (.ok native)) : - yulResultsAgreeOn observableSlots native oracle := by - rcases hOracle with ⟨hsuccess, hreturnValue, hstorage, _hmappings, hevents⟩ - rcases hNative with ⟨hnativeSuccess, hnativeReturnValue, hnativeStorage, hnativeEvents⟩ - exact ⟨ - hnativeSuccess.symm.trans hsuccess, - hnativeReturnValue.symm.trans hreturnValue, - (by - intro slot hslot - exact (hnativeStorage slot hslot).symm.trans (hstorage (IRStorageSlot.ofNat slot))), - hnativeEvents.symm.trans hevents - ⟩ - -/-- The exact semantic bridge still needed before the public theorem can be -retargeted unconditionally to native EVMYulLean. - -This predicate is intentionally concrete: it compares the current -fuel-aligned EVMYulLean-backed interpreter oracle with -`Native.interpretIRRuntimeNative` on the actual `Compiler.emitYul` runtime code -for an `IRContract`, under the same explicit fuel bound and observable -storage-slot set. -/ -def nativeIRRuntimeAgreesWithInterpreter - (fuel : Nat) - (contract : IRContract) - (tx : IRTransaction) - (state : IRState) - (observableSlots : List Nat) : - Prop := - match Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative - fuel contract tx state observableSlots with - | .ok native => - yulResultsAgreeOn observableSlots native - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean fuel (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events) - | .error _ => False +/-- Compose Layer 2 source-to-IR correctness with native EVMYulLean runtime +correctness, without mentioning the legacy Yul interpreter. -/ +private theorem sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + {observableSlots : List Nat} + {source : SourceSemantics.SourceContractResult} + {ir : IRResult} + {native : Except Compiler.Proofs.YulGeneration.Backends.AdapterError YulResult} + (hSourceIR : + Compiler.Proofs.IRGeneration.FunctionBody.sourceResultMatchesIRResult + source ir) + (hNativeIR : + nativeResultsMatchOn observableSlots ir native) : + sourceResultMatchesNativeOn observableSlots source native := by + cases native with + | error err => + cases hNativeIR + | ok yul => + rcases hSourceIR with ⟨hSourceSuccess, hSourceReturn, hSourceStorage, hSourceEvents⟩ + rcases hNativeIR with ⟨hNativeSuccess, hNativeReturn, hNativeStorage, hNativeEvents⟩ + refine ⟨?_, ?_, ?_, ?_⟩ + · exact hSourceSuccess.trans hNativeSuccess + · exact hSourceReturn.trans hNativeReturn + · intro slot hslot + have hStorageAt := + congrArg (fun f => f (IRStorageSlot.ofNat slot)) hSourceStorage + exact hStorageAt.trans (hNativeStorage slot hslot) + · exact hSourceEvents.trans hNativeEvents -/-- Intro form for the native/interpreter bridge obligation. +/-- File-local supported-compiler correctness theorem over native EVMYulLean +runtime adapter execution. -Native-lowering proofs can stay at the harness level: prove that -`interpretIRRuntimeNative` succeeds and that its projected result agrees with -the current interpreter oracle on the requested observable slots. This packages -those two facts as the public `nativeIRRuntimeAgreesWithInterpreter` -obligation consumed by the native EndToEnd seam. -/ -theorem nativeIRRuntimeAgreesWithInterpreter_of_ok_agree - {fuel : Nat} {contract : IRContract} {tx : IRTransaction} - {state : IRState} {observableSlots : List Nat} {native : YulResult} +The theorem target is the native runtime harness backed by +`EvmYul.Yul.callDispatcher`; the only Layer 3 premise is a direct native-vs-IR +`nativeResultsMatchOn` proof for the same generated runtime. -/ +private theorem compile_preserves_native_evmYulLean_of_nativeResultsMatchOn + (model : CompilationModel.CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) (hNative : - Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative - fuel contract tx state observableSlots = .ok native) - (hAgree : - yulResultsAgreeOn observableSlots native - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean fuel (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events)) : - nativeIRRuntimeAgreesWithInterpreter fuel contract tx state observableSlots := by - unfold nativeIRRuntimeAgreesWithInterpreter - rw [hNative] - exact hAgree - -/-- Concrete native execution agreement target after Verity runtime Yul has -successfully lowered to an EVMYulLean contract. - -This is the next proof obligation under the opaque -`nativeIRRuntimeAgreesWithInterpreter` seam: compare the projected native -`callDispatcher` result with the fuel-aligned interpreter oracle on the same -emitted runtime code and observable storage slots. -/ -def nativeCallDispatcherAgreesWithInterpreter - (fuel : Nat) + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := hNative) + +private theorem txNoWrap_of_calldataSizeFits + {tx : IRTransaction} + (h : Function.TxCalldataSizeFitsEvm tx) : + 4 + tx.args.length * 32 < EvmYul.UInt256.size := by + simpa [Function.TxCalldataSizeFitsEvm, Compiler.Constants.evmModulus, + EvmYul.UInt256.size] using h + +/-- The generated selector-hit success prefix is guard-safe for payable +functions whenever the selected ABI argument prefix is present and the full +transaction calldata size fits an EVM word. -/ +private theorem DispatchGuardsSafe.of_payable_of_args_le_of_noWrap + (fn : IRFunction) (tx : IRTransaction) + (hPayable : fn.payable = true) + (hArgs : fn.params.length ≤ tx.args.length) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + DispatchGuardsSafe fn tx := by + refine ⟨Or.inl hPayable, ?_⟩ + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + have hAdd : 4 + fn.params.length * 32 ≤ 4 + tx.args.length * 32 := + Nat.add_le_add_left hMul 4 + exact lt_of_le_of_lt hAdd (by + simpa [Compiler.Constants.evmModulus, EvmYul.UInt256.size] using hNoWrap) + +/-- The generated selector-hit success prefix is guard-safe for non-payable +functions when the transaction value is zero modulo the EVM word modulus, the +selected ABI argument prefix is present, and the full transaction calldata size +fits an EVM word. -/ +private theorem DispatchGuardsSafe.of_nonpayable_zero_of_args_le_of_noWrap + (fn : IRFunction) (tx : IRTransaction) + (hZero : tx.msgValue % Compiler.Constants.evmModulus = 0) + (hArgs : fn.params.length ≤ tx.args.length) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + DispatchGuardsSafe fn tx := by + refine ⟨Or.inr (by + simpa [Compiler.Constants.evmModulus] using hZero), ?_⟩ + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + have hAdd : 4 + fn.params.length * 32 ≤ 4 + tx.args.length * 32 := + Nat.add_le_add_left hMul 4 + exact lt_of_le_of_lt hAdd (by + simpa [Compiler.Constants.evmModulus, EvmYul.UInt256.size] using hNoWrap) + +/-- Package the generated selector-hit success conditions into +`DispatchGuardsSafe`. -/ +theorem DispatchGuardsSafe.of_value_safe_of_args_le_of_noWrap + (fn : IRFunction) (tx : IRTransaction) + (hValue : fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0) + (hArgs : fn.params.length ≤ tx.args.length) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + DispatchGuardsSafe fn tx := by + refine ⟨hValue, ?_⟩ + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + have hAdd : 4 + fn.params.length * 32 ≤ 4 + tx.args.length * 32 := + Nat.add_le_add_left hMul 4 + exact lt_of_le_of_lt hAdd (by + simpa [Compiler.Constants.evmModulus, EvmYul.UInt256.size] using hNoWrap) + +/-- Package value-safety with the generated calldata-threshold bound into +`DispatchGuardsSafe`. + +This is useful for generated guard-failure splits: the short-calldata branch +cannot derive the selected function's threshold from transaction calldata +length, but it also does not need any argument-availability fact. -/ +theorem DispatchGuardsSafe.of_value_safe_of_threshold + (fn : IRFunction) (tx : IRTransaction) + (hValue : fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0) + (hThreshold : 4 + fn.params.length * 32 < EvmYul.UInt256.size) : + DispatchGuardsSafe fn tx := + ⟨hValue, by + simpa [Compiler.Constants.evmModulus, EvmYul.UInt256.size] using + hThreshold⟩ + +private theorem compiledFunctionCalldataThreshold_of_forall₂ + (spec : CompilationModel.CompilationModel) + (tx : IRTransaction) + (hSourceThreshold : + ∀ fn, fn ∈ selectorDispatchedFunctions spec → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + {pairs : List (CompilationModel.FunctionSpec × Nat)} + {irFns : List IRFunction} + (hPairsMem : + ∀ entry, entry ∈ pairs → entry.1 ∈ selectorDispatchedFunctions spec) + (hcompiled : + List.Forall₂ + (fun entry irFn => + CompilationModel.compileFunctionSpec spec.fields spec.events + spec.errors [] entry.2 entry.1 = Except.ok irFn) + pairs irFns) + (irFn : IRFunction) + (hFind : + irFns.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn) : + 4 + irFn.params.length * 32 < EvmYul.UInt256.size := by + induction hcompiled with + | nil => + simp at hFind + | @cons entry headIr tailPairs tailIr hhead htail ih => + by_cases hSelector : headIr.selector = tx.functionSelector + · simp [hSelector] at hFind + rcases hFind with rfl + have hParams : + headIr.params = + entry.1.params.map CompilationModel.Param.toIRParam := + Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_params + spec.fields spec.events spec.errors entry.2 entry.1 headIr hhead + have hLen : headIr.params.length = entry.1.params.length := by + simp [hParams] + rw [hLen] + exact hSourceThreshold entry.1 (hPairsMem entry (by simp)) + · have hFindTail : + tailIr.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn := by + simpa [hSelector] using hFind + exact ih + (fun entry' hMem => + hPairsMem entry' (by simp [hMem])) + hFindTail + +private theorem generatedFunctionCalldataThreshold_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (irFn : IRFunction) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn) : + 4 + irFn.params.length * 32 < EvmYul.UInt256.size := by + have hcompiled := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions + spec selectors hSupported irContract hcompile + exact + compiledFunctionCalldataThreshold_of_forall₂ spec tx + (fun fn hfn => by + simpa [Compiler.Constants.evmModulus, EvmYul.UInt256.size] using + hSupported.selectorFunctionParamCalldataThreshold hfn) + (pairs := SourceSemantics.selectorFunctionPairs spec selectors) + (irFns := irContract.functions) + (fun entry hMem => + by + simpa [SourceSemantics.selectorFunctionPairs] using + (List.of_mem_zip hMem).1) + hcompiled irFn hFind + +/-- Native EVMYulLean whole-runtime composition target. + +Callers can combine any source-to-IR compiler theorem with any native +`nativeIRRuntimeMatchesIR` proof to obtain a source-facing theorem over +`interpretIRRuntimeNative`. -/ +private theorem sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + {fuel : Nat} + {contract : IRContract} + {tx : IRTransaction} + {state : IRState} + {observableSlots : List Nat} + {source : SourceSemantics.SourceContractResult} + (hSourceIR : + Compiler.Proofs.IRGeneration.FunctionBody.sourceResultMatchesIRResult source + (interpretIR contract tx state)) + (hNativeIR : + nativeIRRuntimeMatchesIR fuel contract tx state observableSlots) : + sourceResultMatchesNativeOn observableSlots source + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + fuel contract tx state observableSlots) := + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + hSourceIR hNativeIR + +/-- Positive-fuel raw native dispatcher-exec target against IR directly. -/ +private def nativeDispatcherExecMatchesIRPositive + (fuel' : Nat) (contract : IRContract) (tx : IRTransaction) (state : IRState) (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) : Prop := - yulResultsAgreeOn observableSlots - (Compiler.Proofs.YulGeneration.Backends.Native.projectResult - (YulTransaction.ofIR tx) state.storage state.events - (EvmYul.Yul.callDispatcher fuel (some nativeContract) - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - nativeContract (YulTransaction.ofIR tx) state.storage - (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots - (Compiler.runtimeCode contract) observableSlots)))) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean fuel (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events) - -/-- Lower-level native dispatcher agreement target. - -For positive fuel this compares the interpreter oracle with direct -`EvmYul.Yul.exec` execution of the lowered contract's dispatcher block, after -the same empty call-frame setup and result projection used by `callDispatcher`. -This is the statement-execution preservation obligation needed next for the -generated fragment. The zero-fuel case is kept explicit so the theorem below is -total in `fuel`. -/ -def nativeDispatcherBlockAgreesWithInterpreter - (fuel : Nat) + let initial := + Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode contract) observableSlots) + let nativeResult := + match + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + fuel' nativeContract initial with + | .error err => .error err + | .ok finalState => + let restored := finalState.reviveJump.overwrite? initial |>.setStore initial + .ok (restored, []) + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events nativeResult)) + +/-- File-local canonical generated-runtime dispatcher-exec target against IR. + +This is retained as transition evidence for older internal wrappers. Public +source-level theorems should target the projected `callDispatcher` result or +the newer positive/projected dispatcher packages instead. -/ +private def nativeGeneratedDispatcherExecMatchesIROn (contract : IRContract) (tx : IRTransaction) (state : IRState) (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) : Prop := + let fuel' := sizeOf (Compiler.emitYul contract).runtimeCode let initial := Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract (YulTransaction.ofIR tx) state.storage (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots (Compiler.runtimeCode contract) observableSlots) let nativeResult := - match fuel with - | 0 => - .error EvmYul.Yul.Exception.OutOfFuel - | Nat.succ fuel' => - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherBlockResult - fuel' nativeContract initial - yulResultsAgreeOn observableSlots - (Compiler.Proofs.YulGeneration.Backends.Native.projectResult - (YulTransaction.ofIR tx) state.storage state.events nativeResult) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean fuel (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events) - -/-- Raw native dispatcher-exec agreement target. - -This peels off the `contractDispatcherBlockResult` wrapper too: the remaining -native preservation proof can target the exact `EvmYul.Yul.exec` result for the -lowered dispatcher block, with only the final `callDispatcher` restoration and -return-list projection left around that raw result. -/ -def nativeDispatcherExecAgreesWithInterpreter - (fuel : Nat) + match + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + fuel' nativeContract initial with + | .error err => .error err + | .ok finalState => + let restored := finalState.reviveJump.overwrite? initial |>.setStore initial + .ok (restored, []) + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events nativeResult)) + +/-- Public canonical generated-runtime `EvmYul.Yul.callDispatcher` result. + +The lowered generated runtime is installed in an EVMYulLean state and run +through `callDispatcher` at canonical generated-runtime fuel, then projected +onto the proof-side observable Yul result surface. -/ +noncomputable def nativeGeneratedCallDispatcherResultOf (contract : IRContract) (tx : IRTransaction) (state : IRState) (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) : - Prop := + Except Compiler.Proofs.YulGeneration.Backends.AdapterError YulResult := + let fuel := Nat.succ (sizeOf (Compiler.emitYul contract).runtimeCode) let initial := Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract (YulTransaction.ofIR tx) state.storage (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots (Compiler.runtimeCode contract) observableSlots) - let nativeResult := - match fuel with - | 0 => - .error EvmYul.Yul.Exception.OutOfFuel - | Nat.succ fuel' => - match - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - fuel' nativeContract initial with - | .error err => .error err - | .ok finalState => - let restored := finalState.reviveJump.overwrite? initial |>.setStore initial - .ok (restored, []) - yulResultsAgreeOn observableSlots + .ok (Compiler.Proofs.YulGeneration.Backends.Native.projectResult - (YulTransaction.ofIR tx) state.storage state.events nativeResult) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean fuel (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events) - -/-- Positive-fuel raw native dispatcher-exec agreement target. - -This is the same selected-dispatcher obligation as -`nativeDispatcherExecAgreesWithInterpreter (Nat.succ fuel')`, but without the -dead zero-fuel branch. Concrete generated dispatchers such as SimpleStorage use -the compiler-emitted runtime size plus one as fuel, so their remaining seam can -target this smaller positive-fuel shape directly. -/ -def nativeDispatcherExecAgreesWithInterpreterPositive - (fuel' : Nat) + (YulTransaction.ofIR tx) state.storage state.events + (EvmYul.Yul.callDispatcher fuel (some nativeContract) initial)) + +/-- File-local canonical generated-runtime `EvmYul.Yul.callDispatcher` target +against IR. + +This is the direct native entrypoint-facing form of +`nativeGeneratedDispatcherExecMatchesIROn`: the lowered generated runtime is +installed in an EVMYulLean state and run through `callDispatcher` at canonical +generated-runtime fuel. -/ +private def nativeGeneratedCallDispatcherMatchesIROn (contract : IRContract) (tx : IRTransaction) (state : IRState) (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) : Prop := + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (nativeGeneratedCallDispatcherResultOf contract tx state observableSlots + nativeContract) + +private theorem nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + {contract : IRContract} {tx : IRTransaction} {state : IRState} + {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hMatch : + nativeGeneratedDispatcherExecMatchesIROn contract tx state + observableSlots nativeContract) : + nativeGeneratedCallDispatcherMatchesIROn contract tx state observableSlots + nativeContract := by + simpa [nativeGeneratedCallDispatcherMatchesIROn, + nativeGeneratedCallDispatcherResultOf, + nativeGeneratedDispatcherExecMatchesIROn, + Compiler.Proofs.YulGeneration.Backends.Native.callDispatcher_succ_eq_callDispatcherBlockResult, + Compiler.Proofs.YulGeneration.Backends.Native.callDispatcherBlockResult_initialState_eq_contractDispatcherBlockResult, + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherBlockResult_eq_execResult] using hMatch + +/-- Re-target a native result match from the selected IR function body to the +top-level IR interpreter, once selector-hit success guards are known. -/ +theorem nativeResultsMatchOn_interpretIR_of_execIRFunction_guards + (contract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) + (native : Except Compiler.Proofs.YulGeneration.Backends.AdapterError + YulResult) + (hFind : + contract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hValue : + fn.payable = false → + tx.msgValue % Compiler.Constants.evmModulus = 0) + (hArgs : fn.params.length ≤ tx.args.length) + (hMatch : + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + native) : + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + native := by + rw [interpretIR_eq_execIRFunction_of_find?_some_guards + contract tx state fn hFind hValue hArgs] + exact hMatch + +/-- `DispatchGuardsSafe`-flavored retargeting from selected function-body IR +semantics to the top-level IR interpreter. -/ +theorem nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + (contract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) + (native : Except Compiler.Proofs.YulGeneration.Backends.AdapterError + YulResult) + (hFind : + contract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) + (hMatch : + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + native) : + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + native := + nativeResultsMatchOn_interpretIR_of_execIRFunction_guards + contract tx state observableSlots fn native hFind + (fun hNonPayable => + Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable + fn tx hguards hNonPayable) + hArgs hMatch + +/-- Native observable match for the selected-function non-payable value guard +revert. This is the IR-side target needed by the generated native +`callvalue()` guard-failure branch. -/ +theorem nativeResultsMatchOn_interpretIR_revert_of_nonpayable_nonzero + (contract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) + (hFind : + contract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hNonPayable : fn.payable = false) + (hNonzero : tx.msgValue % Compiler.Constants.evmModulus ≠ 0) : + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok + { success := false + returnValue := none + finalStorage := state.storage + finalMappings := Compiler.Proofs.storageAsMappings state.storage + events := state.events }) := by + rw [interpretIR_eq_revert_of_find?_some_nonpayable_nonzero + contract tx state fn hFind hNonPayable hNonzero] + simp [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn] + +/-- Native observable match for the selected-function calldata arity guard +revert. This is the IR-side target needed by the generated native +`calldatasize()` guard-failure branch. -/ +theorem nativeResultsMatchOn_interpretIR_revert_of_args_short + (contract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) + (hFind : + contract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hValue : + fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok + { success := false + returnValue := none + finalStorage := state.storage + finalMappings := Compiler.Proofs.storageAsMappings state.storage + events := state.events }) := by + rw [interpretIR_eq_revert_of_find?_some_args_short + contract tx state fn hFind hValue hArgsShort] + simp [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn] + +/-- Projected native `Revert` result matches the selected-function non-payable +value guard failure in `interpretIR`. -/ +theorem nativeResultsMatchOn_projectResult_revert_of_nonpayable_nonzero + (contract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) + (hFind : + contract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hNonPayable : fn.payable = false) + (hNonzero : tx.msgValue % Compiler.Constants.evmModulus ≠ 0) : + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.error EvmYul.Yul.Exception.Revert))) := by + simpa using + (nativeResultsMatchOn_interpretIR_revert_of_nonpayable_nonzero + contract tx state observableSlots fn hFind hNonPayable hNonzero) + +/-- Projected native `Revert` result matches the selected-function calldata +arity guard failure in `interpretIR`. -/ +theorem nativeResultsMatchOn_projectResult_revert_of_args_short + (contract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) + (hFind : + contract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hValue : + fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.error EvmYul.Yul.Exception.Revert))) := by + simpa using + (nativeResultsMatchOn_interpretIR_revert_of_args_short + contract tx state observableSlots fn hFind hValue hArgsShort) + +/-- Public native contract shell produced by helper-free generated dispatcher +lowering. -/ +def nativeGeneratedDispatcherContractOf + (dispatcher : List EvmYul.Yul.Ast.Stmt) : + EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block dispatcher + functions := + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) } + +/-- Public native contract shell produced by generated dispatcher lowering +when the runtime includes the native `mappingSlot` helper. -/ +def nativeGeneratedDispatcherContractWithMappingOf + (dispatcher : List EvmYul.Yul.Ast.Stmt) : + EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block dispatcher + functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) } + +/-- Canonical native dispatcher fuel for the generated runtime surface. -/ +private noncomputable abbrev nativeRuntimeDispatcherFuel (contract : IRContract) : Nat := + sizeOf (Compiler.emitYul contract).runtimeCode + +/-- Canonical native runtime fuel. `interpretIRRuntimeNative` spends one fuel +step before dispatching into the lowered runtime. -/ +private noncomputable abbrev nativeRuntimeFuel (contract : IRContract) : Nat := + Nat.succ (nativeRuntimeDispatcherFuel contract) + +private theorem sizeOf_list_ge_length {α : Type _} [SizeOf α] (xs : List α) : + sizeOf xs ≥ xs.length + 1 := by + induction xs with + | nil => + simp + | cons _ xs ih => + simp + omega + +/-- The concrete no-fallback/no-receive generated dispatcher has enough +structural size to cover the selector prologue and one lazy-switch pass for +every lowered switch case. This is the fuel arithmetic fact needed before the +structural dispatcher lemmas can be retargeted to canonical generated-runtime +fuel. -/ +private theorem sizeOf_buildSwitch_noFallback_noReceive_ge_source_cases_length + (fns : List IRFunction) : + sizeOf [Compiler.CodegenCommon.buildSwitch fns none none] ≥ + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + fns).length + 19 := by + unfold Compiler.CodegenCommon.buildSwitch + simp only [ite_false, Bool.false_eq_true, + Compiler.CodegenCommon.defaultDispatchCase] + have hcases : + (fns.map (fun fn => + (fn.selector, + Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" + ([Compiler.CodegenCommon.calldatasizeGuard fn.params.length] ++ + fn.body)))) = + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + fns := by + induction fns with + | nil => + simp [Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases] + | cons fn rest ih => + cases hpay : fn.payable <;> + simp [Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases, + Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody, + Compiler.CodegenCommon.dispatchBody, + Compiler.CodegenCommon.callvalueGuard, + Compiler.CodegenCommon.calldatasizeGuard, hpay] + rw [hcases] + have hLen := + sizeOf_list_ge_length + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + fns) + set cases := + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases fns + set defaultStmts : List Compiler.Yul.YulStmt := + [Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "revert" + [Compiler.Yul.YulExpr.lit 0, Compiler.Yul.YulExpr.lit 0])] + set sw := Compiler.Yul.YulStmt.switch + (Compiler.Yul.YulExpr.call "shr" + [Compiler.Yul.YulExpr.lit Compiler.Constants.selectorShift, + Compiler.Yul.YulExpr.call "calldataload" + [Compiler.Yul.YulExpr.lit 0]]) + cases (some defaultStmts) + set if2 := Compiler.Yul.YulStmt.if_ + (Compiler.Yul.YulExpr.ident "__has_selector") [sw] + let block := Compiler.Yul.YulStmt.block + [Compiler.Yul.YulStmt.let_ "__has_selector" + (Compiler.Yul.YulExpr.call "iszero" + [Compiler.Yul.YulExpr.call "lt" + [Compiler.Yul.YulExpr.call "calldatasize" [], + Compiler.Yul.YulExpr.lit 4]]), + Compiler.Yul.YulStmt.if_ + (Compiler.Yul.YulExpr.call "iszero" + [Compiler.Yul.YulExpr.ident "__has_selector"]) defaultStmts, + if2] + have hBlock : sizeOf block ≥ 18 + sizeOf cases := by + simp [block, if2, sw] + omega + have hBlockLen : cases.length + 19 ≤ sizeOf block := by + omega + have hList : sizeOf block ≤ sizeOf [block] := by + simp + omega + exact Nat.le_trans hBlockLen hList + +private theorem sizeOf_buildSwitch_noFallback_noReceive_ge_source_cases_length_plus24 + (fns : List IRFunction) : + sizeOf [Compiler.CodegenCommon.buildSwitch fns none none] ≥ + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + fns).length + 24 := by + unfold Compiler.CodegenCommon.buildSwitch + simp only [ite_false, Bool.false_eq_true, + Compiler.CodegenCommon.defaultDispatchCase] + have hcases : + (fns.map (fun fn => + (fn.selector, + Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" + ([Compiler.CodegenCommon.calldatasizeGuard fn.params.length] ++ + fn.body)))) = + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + fns := by + induction fns with + | nil => + simp [Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases] + | cons fn rest ih => + cases hpay : fn.payable <;> + simp [Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases, + Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody, + Compiler.CodegenCommon.dispatchBody, + Compiler.CodegenCommon.callvalueGuard, + Compiler.CodegenCommon.calldatasizeGuard, hpay] + rw [hcases] + have hLen := + sizeOf_list_ge_length + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + fns) + set cases := + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases fns + set defaultStmts : List Compiler.Yul.YulStmt := + [Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "revert" + [Compiler.Yul.YulExpr.lit 0, Compiler.Yul.YulExpr.lit 0])] + set sw := Compiler.Yul.YulStmt.switch + (Compiler.Yul.YulExpr.call "shr" + [Compiler.Yul.YulExpr.lit Compiler.Constants.selectorShift, + Compiler.Yul.YulExpr.call "calldataload" + [Compiler.Yul.YulExpr.lit 0]]) + cases (some defaultStmts) + set if2 := Compiler.Yul.YulStmt.if_ + (Compiler.Yul.YulExpr.ident "__has_selector") [sw] + let block := Compiler.Yul.YulStmt.block + [Compiler.Yul.YulStmt.let_ "__has_selector" + (Compiler.Yul.YulExpr.call "iszero" + [Compiler.Yul.YulExpr.call "lt" + [Compiler.Yul.YulExpr.call "calldatasize" [], + Compiler.Yul.YulExpr.lit 4]]), + Compiler.Yul.YulStmt.if_ + (Compiler.Yul.YulExpr.call "iszero" + [Compiler.Yul.YulExpr.ident "__has_selector"]) defaultStmts, + if2] + have hBlock : sizeOf block ≥ 23 + sizeOf cases := by + simp [block, if2, sw] + omega + have hBlockLen : cases.length + 24 ≤ sizeOf block := by + omega + have hList : sizeOf block ≤ sizeOf [block] := by + simp + omega + exact Nat.le_trans hBlockLen hList + +private theorem sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + {reservedNames : List String} {n0 : Nat} + {cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)} {midN : Nat} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerCases : + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN)) : + cases'.length + 19 ≤ + sizeOf (Compiler.emitYul irContract).runtimeCode := by + have hRuntime : + (Compiler.emitYul irContract).runtimeCode = + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] := + Compiler.Proofs.YulGeneration.Backends.Native.emitYul_runtimeCode_eq_single_dispatcher_of_noMapping_noInternals_noFallback_noReceive + irContract hNoMapping + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile)) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile) + have hLen : + cases'.length = + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions).length := + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds_length_eq + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + midN + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) cases' hLowerCases + have hSize := + sizeOf_buildSwitch_noFallback_noReceive_ge_source_cases_length + irContract.functions + rw [hRuntime, hLen] + exact hSize + +private theorem sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length_plus24 + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + {reservedNames : List String} {n0 : Nat} + {cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)} {midN : Nat} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerCases : + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN)) : + cases'.length + 24 ≤ + sizeOf (Compiler.emitYul irContract).runtimeCode := by + have hRuntime : + (Compiler.emitYul irContract).runtimeCode = + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] := + Compiler.Proofs.YulGeneration.Backends.Native.emitYul_runtimeCode_eq_single_dispatcher_of_noMapping_noInternals_noFallback_noReceive + irContract hNoMapping + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile)) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile) + have hLen : + cases'.length = + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions).length := + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds_length_eq + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + midN + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) cases' hLowerCases + have hSize := + sizeOf_buildSwitch_noFallback_noReceive_ge_source_cases_length_plus24 + irContract.functions + rw [hRuntime, hLen] + exact hSize + +private theorem sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + {reservedNames : List String} {switchStart : Nat} + {cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)} {midN : Nat} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerCases : + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN)) : + cases'.length + 19 ≤ + sizeOf (Compiler.emitYul irContract).runtimeCode := by + have hInternals : + irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + have hNoFallback : + irContract.fallbackEntrypoint = none := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile + have hNoReceive : + irContract.receiveEntrypoint = none := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile + have hLen : + cases'.length = + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions).length := + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds_length_eq + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + midN + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) cases' hLowerCases + have hSize := + sizeOf_buildSwitch_noFallback_noReceive_ge_source_cases_length + irContract.functions + rw [hLen] + refine Nat.le_trans hSize ?_ + unfold Compiler.emitYul Compiler.CodegenCommon.emitYul + Compiler.CodegenCommon.runtimeCode + simp only [hMapping, hInternals, hNoFallback, hNoReceive, if_true, + List.singleton_append, List.append_nil] + simp only [Compiler.CodegenCommon.mappingSlotFuncAt] + simp + +private theorem sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length_plus24 + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + {reservedNames : List String} {switchStart : Nat} + {cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)} {midN : Nat} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerCases : + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN)) : + cases'.length + 24 ≤ + sizeOf (Compiler.emitYul irContract).runtimeCode := by + have hInternals : + irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + have hNoFallback : + irContract.fallbackEntrypoint = none := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile + have hNoReceive : + irContract.receiveEntrypoint = none := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile + have hLen : + cases'.length = + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions).length := + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds_length_eq + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + midN + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) cases' hLowerCases + have hSize := + sizeOf_buildSwitch_noFallback_noReceive_ge_source_cases_length_plus24 + irContract.functions + rw [hLen] + refine Nat.le_trans hSize ?_ + unfold Compiler.emitYul Compiler.CodegenCommon.emitYul + Compiler.CodegenCommon.runtimeCode + simp only [hMapping, hInternals, hNoFallback, hNoReceive, if_true, + List.singleton_append, List.append_nil] + simp only [Compiler.CodegenCommon.mappingSlotFuncAt] + simp + +/-- Projected native dispatcher-exec result equality used by the public native +EndToEnd theorems. + +This is a result-shape obligation, not a dispatcher-vs-IR semantic premise: it +states that the native dispatcher execution at `fuel'`, after the standard +jump/store restoration and projection, yields the supplied `YulResult`. -/ +abbrev nativeProjectedDispatcherResultEq + (fuel' : Nat) (contract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) (nativeYul : YulResult) : + Prop := let initial := - Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract - (YulTransaction.ofIR tx) state.storage + Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract (YulTransaction.ofIR tx) state.storage (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots (Compiler.runtimeCode contract) observableSlots) let nativeResult := - match - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + match Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult fuel' nativeContract initial with | .error err => .error err | .ok finalState => let restored := finalState.reviveJump.overwrite? initial |>.setStore initial .ok (restored, []) - yulResultsAgreeOn observableSlots - (Compiler.Proofs.YulGeneration.Backends.Native.projectResult - (YulTransaction.ofIR tx) state.storage state.events nativeResult) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ fuel') (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events) - -/-- Intro form for the positive-fuel raw dispatcher-exec bridge when native -execution finishes normally. - -This is the positive-fuel counterpart of -`nativeDispatcherExecAgreesWithInterpreter_of_exec_ok_agree`, avoiding the -generic zero-fuel branch for generated dispatcher proofs that already know their -fuel is `Nat.succ fuel'`. -/ -theorem nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_ok_agree + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events nativeResult = + nativeYul + +/-- File-local lift from a direct positive dispatcher-exec native-vs-IR proof +through the generated native runtime harness. + +The exported theorem surface should not ask callers to supply this generic +premise; concrete public theorems discharge it internally. -/ +private theorem nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_positive_match {fuel' : Nat} {contract : IRContract} {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} {nativeContract : EvmYul.Yul.Ast.YulContract} - {finalState : EvmYul.Yul.State} - (hExec : - let initial := - Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract - (YulTransaction.ofIR tx) state.storage - (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots - (Compiler.runtimeCode contract) observableSlots) - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - fuel' nativeContract initial = - .ok finalState) - (hAgree : - let initial := - Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract - (YulTransaction.ofIR tx) state.storage - (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots - (Compiler.runtimeCode contract) observableSlots) - yulResultsAgreeOn observableSlots - (Compiler.Proofs.YulGeneration.Backends.Native.projectResult - (YulTransaction.ofIR tx) state.storage state.events - (.ok - (finalState.reviveJump.overwrite? initial |>.setStore initial, - []))) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ fuel') (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events)) : - nativeDispatcherExecAgreesWithInterpreterPositive fuel' contract tx state - observableSlots nativeContract := by - unfold nativeDispatcherExecAgreesWithInterpreterPositive - simp [hExec] - exact hAgree + (hPrefixUnique : + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique + ((if contract.usesMapping then [Compiler.mappingSlotFuncAt 0] else []) ++ + contract.internalFunctions) = true) + (hInternals : ∀ stmt, stmt ∈ contract.internalFunctions → + ∃ name params rets body, stmt = Yul.YulStmt.funcDef name params rets body) + (hExternalBodies : ∀ fn, fn ∈ contract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false) + (hInternalBodies : ∀ name params rets body, + Yul.YulStmt.funcDef name params rets body ∈ contract.internalFunctions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + body = false) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul contract).runtimeCode = .ok nativeContract) + (hEnv : + Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : + nativeDispatcherExecMatchesIRPositive fuel' contract tx state + observableSlots nativeContract) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') contract tx state observableSlots := by + unfold nativeIRRuntimeMatchesIR + rw [Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative_succ_eq_contractDispatcherExecResult_of_lowerRuntimeContractNative + fuel' contract tx state observableSlots nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment_emitYul_runtimeCode_noFallback_noReceive + contract hPrefixUnique hInternals hExternalBodies hInternalBodies + hNoFallback hNoReceive) + hLower hEnv] + unfold nativeDispatcherExecMatchesIRPositive at hMatch + simpa using hMatch -/-- Intro form for the positive-fuel raw dispatcher-exec bridge when native -execution halts through EVMYulLean's Yul halt channel (`stop`/`return`). -/ -theorem nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_yulHalt_agree +private theorem nativeDispatcherExecMatchesIRPositive_of_project_eq_match {fuel' : Nat} {contract : IRContract} {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} {nativeContract : EvmYul.Yul.Ast.YulContract} - {haltState : EvmYul.Yul.State} {haltValue : EvmYul.Yul.Ast.Literal} - (hExec : - let initial := + {nativeYul : YulResult} + (hProject : nativeProjectedDispatcherResultEq fuel' contract tx state + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok nativeYul)) : + nativeDispatcherExecMatchesIRPositive fuel' contract tx state + observableSlots nativeContract := by + have hProject' : + (let initial := Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract (YulTransaction.ofIR tx) state.storage (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots (Compiler.runtimeCode contract) observableSlots) - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - fuel' nativeContract initial = - .error (.YulHalt haltState haltValue)) - (hAgree : - yulResultsAgreeOn observableSlots + let nativeResult := + match + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + fuel' nativeContract initial with + | .error err => .error err + | .ok finalState => + let restored := finalState.reviveJump.overwrite? initial |>.setStore initial + .ok (restored, []) + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events nativeResult) = + nativeYul := by + simpa [nativeProjectedDispatcherResultEq] using hProject + unfold nativeDispatcherExecMatchesIRPositive + change + let initial := + Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode contract) observableSlots) + let nativeResult := + match + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + fuel' nativeContract initial with + | .error err => .error err + | .ok finalState => + let restored := finalState.reviveJump.overwrite? initial |>.setStore initial + .ok (restored, []) + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok (Compiler.Proofs.YulGeneration.Backends.Native.projectResult - (YulTransaction.ofIR tx) state.storage state.events - (.error (.YulHalt haltState haltValue))) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ fuel') (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events)) : - nativeDispatcherExecAgreesWithInterpreterPositive fuel' contract tx state - observableSlots nativeContract := by - unfold nativeDispatcherExecAgreesWithInterpreterPositive - simp [hExec] - exact hAgree + (YulTransaction.ofIR tx) state.storage state.events nativeResult)) + simpa [hProject'] using hMatch -/-- Intro form for a positive-fuel raw dispatcher Yul halt when a concrete -native execution lemma already packages the projected `YulResult`. +private theorem nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_project_eq_match + {fuel' : Nat} {contract : IRContract} {tx : IRTransaction} + {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + {nativeYul : YulResult} + (hPrefixUnique : + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique + ((if contract.usesMapping then [Compiler.mappingSlotFuncAt 0] else []) ++ + contract.internalFunctions) = true) + (hInternals : ∀ stmt, stmt ∈ contract.internalFunctions → + ∃ name params rets body, stmt = Yul.YulStmt.funcDef name params rets body) + (hExternalBodies : ∀ fn, fn ∈ contract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false) + (hInternalBodies : ∀ name params rets body, + Yul.YulStmt.funcDef name params rets body ∈ contract.internalFunctions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + body = false) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul contract).runtimeCode = .ok nativeContract) + (hEnv : + Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' contract tx state + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') contract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_positive_match + hPrefixUnique hInternals hExternalBodies hInternalBodies hNoFallback + hNoReceive hLower hEnv + (nativeDispatcherExecMatchesIRPositive_of_project_eq_match hProject hMatch) -The SimpleStorage store/retrieve selector-hit lemmas expose both the exact -`YulHalt` and the exact native projection. This helper turns those facts plus -agreement for the named projection into the raw dispatcher bridge obligation. -/ -theorem nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_yulHalt_project_eq_agree +private theorem nativeDispatcherExecMatchesIRPositive_of_exec_yulHalt_project_eq_match {fuel' : Nat} {contract : IRContract} {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} {nativeContract : EvmYul.Yul.Ast.YulContract} @@ -413,56 +1152,17 @@ theorem nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_yulHalt_projec (YulTransaction.ofIR tx) state.storage state.events (.error (.YulHalt haltState haltValue)) = nativeYul) - (hAgree : - yulResultsAgreeOn observableSlots nativeYul - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ fuel') (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events)) : - nativeDispatcherExecAgreesWithInterpreterPositive fuel' contract tx state + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok nativeYul)) : + nativeDispatcherExecMatchesIRPositive fuel' contract tx state observableSlots nativeContract := by - apply nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_yulHalt_agree - · exact hExec - · rw [hProject] - exact hAgree - -/-- Intro form for the positive-fuel raw dispatcher-exec bridge when native -execution fails through a non-halt EVMYulLean exception. -/ -theorem nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_error_agree - {fuel' : Nat} {contract : IRContract} {tx : IRTransaction} - {state : IRState} {observableSlots : List Nat} - {nativeContract : EvmYul.Yul.Ast.YulContract} - {err : EvmYul.Yul.Exception} - (hExec : - let initial := - Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract - (YulTransaction.ofIR tx) state.storage - (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots - (Compiler.runtimeCode contract) observableSlots) - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - fuel' nativeContract initial = - .error err) - (hAgree : - yulResultsAgreeOn observableSlots - (Compiler.Proofs.YulGeneration.Backends.Native.projectResult - (YulTransaction.ofIR tx) state.storage state.events (.error err)) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ fuel') (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events)) : - nativeDispatcherExecAgreesWithInterpreterPositive fuel' contract tx state - observableSlots nativeContract := by - unfold nativeDispatcherExecAgreesWithInterpreterPositive + unfold nativeDispatcherExecMatchesIRPositive simp [hExec] - exact hAgree + rw [← hProject] at hMatch + simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectResult] using hMatch -/-- Intro form for a positive-fuel raw dispatcher error when a concrete native -execution lemma already packages the projected `YulResult`. - -Generated dispatcher proofs such as SimpleStorage's default/revert branch prove -two facts at the lowered-switch boundary: the raw EVMYulLean exception, and the -exact `projectResult` value. This helper consumes that pair directly, so the -remaining case proof only has to establish agreement for the named projected -result. -/ -theorem nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_error_project_eq_agree +private theorem nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match {fuel' : Nat} {contract : IRContract} {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} {nativeContract : EvmYul.Yul.Ast.YulContract} @@ -480,4506 +1180,33741 @@ theorem nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_error_project_ Compiler.Proofs.YulGeneration.Backends.Native.projectResult (YulTransaction.ofIR tx) state.storage state.events (.error err) = nativeYul) - (hAgree : - yulResultsAgreeOn observableSlots nativeYul - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ fuel') (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events)) : - nativeDispatcherExecAgreesWithInterpreterPositive fuel' contract tx state + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR contract tx state) + (.ok nativeYul)) : + nativeDispatcherExecMatchesIRPositive fuel' contract tx state observableSlots nativeContract := by - apply nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_error_agree - · exact hExec - · rw [hProject] - exact hAgree - -/-- Lift the positive-fuel dispatcher-exec obligation back to the generic raw -dispatcher bridge shape consumed by the existing native theorem stack. -/ -theorem nativeDispatcherExecAgreesWithInterpreter_of_positive - {fuel' : Nat} {contract : IRContract} {tx : IRTransaction} - {state : IRState} {observableSlots : List Nat} - {nativeContract : EvmYul.Yul.Ast.YulContract} - (hAgree : - nativeDispatcherExecAgreesWithInterpreterPositive fuel' contract tx state - observableSlots nativeContract) : - nativeDispatcherExecAgreesWithInterpreter (Nat.succ fuel') contract tx state - observableSlots nativeContract := by - unfold nativeDispatcherExecAgreesWithInterpreterPositive at hAgree - unfold nativeDispatcherExecAgreesWithInterpreter - simpa using hAgree - -/-- Intro form for the positive-fuel raw dispatcher-exec bridge when native -execution finishes normally. - -The remaining generated-fragment simulation can prove a concrete -`contractDispatcherExecResult = .ok finalState` fact, then prove observable -agreement for the restored/projected call-dispatcher result. This theorem -packages that pair as the public raw-dispatcher agreement obligation. -/ -theorem nativeDispatcherExecAgreesWithInterpreter_of_exec_ok_agree - {fuel' : Nat} {contract : IRContract} {tx : IRTransaction} - {state : IRState} {observableSlots : List Nat} - {nativeContract : EvmYul.Yul.Ast.YulContract} - {finalState : EvmYul.Yul.State} - (hExec : - let initial := - Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract - (YulTransaction.ofIR tx) state.storage - (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots - (Compiler.runtimeCode contract) observableSlots) - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - fuel' nativeContract initial = - .ok finalState) - (hAgree : - let initial := - Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract - (YulTransaction.ofIR tx) state.storage - (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots - (Compiler.runtimeCode contract) observableSlots) - yulResultsAgreeOn observableSlots - (Compiler.Proofs.YulGeneration.Backends.Native.projectResult - (YulTransaction.ofIR tx) state.storage state.events - (.ok - (finalState.reviveJump.overwrite? initial |>.setStore initial, - []))) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ fuel') (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events)) : - nativeDispatcherExecAgreesWithInterpreter (Nat.succ fuel') contract tx state - observableSlots nativeContract := by - unfold nativeDispatcherExecAgreesWithInterpreter + unfold nativeDispatcherExecMatchesIRPositive simp [hExec] - exact hAgree + rw [← hProject] at hMatch + simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectResult] using hMatch -/-- Intro form for the positive-fuel raw dispatcher-exec bridge when native -execution halts through EVMYulLean's Yul halt channel (`stop`/`return`). -/ -theorem nativeDispatcherExecAgreesWithInterpreter_of_exec_yulHalt_agree - {fuel' : Nat} {contract : IRContract} {tx : IRTransaction} - {state : IRState} {observableSlots : List Nat} - {nativeContract : EvmYul.Yul.Ast.YulContract} - {haltState : EvmYul.Yul.State} {haltValue : EvmYul.Yul.Ast.Literal} - (hExec : - let initial := - Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract - (YulTransaction.ofIR tx) state.storage - (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots - (Compiler.runtimeCode contract) observableSlots) - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - fuel' nativeContract initial = - .error (.YulHalt haltState haltValue)) - (hAgree : - yulResultsAgreeOn observableSlots - (Compiler.Proofs.YulGeneration.Backends.Native.projectResult - (YulTransaction.ofIR tx) state.storage state.events - (.error (.YulHalt haltState haltValue))) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ fuel') (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events)) : - nativeDispatcherExecAgreesWithInterpreter (Nat.succ fuel') contract tx state - observableSlots nativeContract := by - unfold nativeDispatcherExecAgreesWithInterpreter - simp [hExec] - exact hAgree +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive + (fuel : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 19) + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions } := by + let nativeContract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_projectResult_eq + fuel tx.functionSelector irContract.functions inner functions + (YulTransaction.ofIR tx) state.storage state.events materializedSlots + hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, hLowerCases, hExec, hProject⟩ + refine ⟨reservedNames, n0, cases', midN, hLowerCases, ?_⟩ + unfold nativeDispatcherExecMatchesIRPositive + dsimp [nativeContract, materializedSlots] at hExec hProject ⊢ + rw [hExec, hProject] + simp [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn, + Compiler.Proofs.IRGeneration.interpretIR, hFind] -/-- Intro form for the positive-fuel raw dispatcher-exec bridge when native -execution fails through a non-halt EVMYulLean exception. +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_atFuel + (fuel' : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + (cases'.length + 19 ≤ fuel' → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let nativeContract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_atFuel_projectResult_eq + fuel' tx.functionSelector irContract.functions inner functions + (YulTransaction.ofIR tx) state.storage state.events materializedSlots + hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, hLowerCases, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, hLowerCases, ?_⟩ + intro hFuel + rcases hCont hFuel with ⟨hExec, hProject⟩ + unfold nativeDispatcherExecMatchesIRPositive + dsimp [nativeContract, materializedSlots] at hExec hProject ⊢ + rw [hExec, hProject] + simp [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn, + Compiler.Proofs.IRGeneration.interpretIR, hFind] -This is useful for revert/fail-closed generated-fragment cases: after proving -the raw native exception and the projected oracle agreement, callers can close -the same raw-dispatcher obligation consumed by the public native theorem seam. -/ -theorem nativeDispatcherExecAgreesWithInterpreter_of_exec_error_agree - {fuel' : Nat} {contract : IRContract} {tx : IRTransaction} - {state : IRState} {observableSlots : List Nat} - {nativeContract : EvmYul.Yul.Ast.YulContract} - {err : EvmYul.Yul.Exception} - (hExec : - let initial := - Compiler.Proofs.YulGeneration.Backends.Native.initialState nativeContract - (YulTransaction.ofIR tx) state.storage - (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots - (Compiler.runtimeCode contract) observableSlots) - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - fuel' nativeContract initial = - .error err) - (hAgree : - yulResultsAgreeOn observableSlots - (Compiler.Proofs.YulGeneration.Backends.Native.projectResult - (YulTransaction.ofIR tx) state.storage state.events (.error err)) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ fuel') (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events)) : - nativeDispatcherExecAgreesWithInterpreter (Nat.succ fuel') contract tx state - observableSlots nativeContract := by - unfold nativeDispatcherExecAgreesWithInterpreter - simp [hExec] - exact hAgree +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_withSwitchIds + (fuel : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 19) + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions } := by + let nativeContract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_withSwitchIds_projectResult_eq + fuel tx.functionSelector reservedNames n0 irContract.functions inner next + functions (YulTransaction.ofIR tx) state.storage state.events materializedSlots + hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨switchStart, cases', midN, hLowerCases, hExec, hProject⟩ + refine ⟨switchStart, cases', midN, hLowerCases, ?_⟩ + unfold nativeDispatcherExecMatchesIRPositive + dsimp [nativeContract, materializedSlots] at hExec hProject ⊢ + rw [hExec, hProject] + simp [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn, + Compiler.Proofs.IRGeneration.interpretIR, hFind] -/-- Lift raw lowered-dispatcher `EvmYul.Yul.exec` agreement to the -dispatcher-block bridge obligation. -/ -theorem nativeDispatcherBlockAgreesWithInterpreter_of_exec_agree - {fuel : Nat} {contract : IRContract} {tx : IRTransaction} - {state : IRState} {observableSlots : List Nat} - {nativeContract : EvmYul.Yul.Ast.YulContract} - (hAgree : - nativeDispatcherExecAgreesWithInterpreter fuel contract tx state - observableSlots nativeContract) : - nativeDispatcherBlockAgreesWithInterpreter fuel contract tx state - observableSlots nativeContract := by - unfold nativeDispatcherExecAgreesWithInterpreter at hAgree - unfold nativeDispatcherBlockAgreesWithInterpreter - cases fuel with - | zero => - simpa using hAgree - | succ fuel' => - simpa [Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherBlockResult_eq_execResult] - using hAgree - -/-- Lift dispatcher-block execution agreement to the existing -`callDispatcher`-level bridge obligation. -/ -theorem nativeCallDispatcherAgreesWithInterpreter_of_dispatcherBlock_agree - {fuel : Nat} {contract : IRContract} {tx : IRTransaction} - {state : IRState} {observableSlots : List Nat} - {nativeContract : EvmYul.Yul.Ast.YulContract} - (hAgree : - nativeDispatcherBlockAgreesWithInterpreter fuel contract tx state - observableSlots nativeContract) : - nativeCallDispatcherAgreesWithInterpreter fuel contract tx state - observableSlots nativeContract := by - unfold nativeDispatcherBlockAgreesWithInterpreter at hAgree - unfold nativeCallDispatcherAgreesWithInterpreter - cases fuel with - | zero => - simpa [Compiler.Proofs.YulGeneration.Backends.Native.callDispatcher_zero] - using hAgree - | succ fuel' => - rw [Compiler.Proofs.YulGeneration.Backends.Native.callDispatcher_succ_eq_callDispatcherBlockResult] - rw [Compiler.Proofs.YulGeneration.Backends.Native.callDispatcherBlockResult_initialState_eq_contractDispatcherBlockResult] - simpa using hAgree - -/-- Discharge the public native/interpreter bridge from concrete native -lowering, selected-path environment validation, and projected -`callDispatcher` agreement. - -After this theorem, generated-fragment work can focus on facts about -`lowerRuntimeContractNative`, `validateNativeRuntimeEnvironment`, and -`EvmYul.Yul.callDispatcher` rather than re-opening the public native harness -wrapper. -/ -theorem nativeIRRuntimeAgreesWithInterpreter_of_lowered_callDispatcher_agree - {fuel : Nat} {contract : IRContract} {tx : IRTransaction} - {state : IRState} {observableSlots : List Nat} - {nativeContract : EvmYul.Yul.Ast.YulContract} - (hFragment : Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment - (Compiler.emitYul contract).runtimeCode = true) - (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative - (Compiler.emitYul contract).runtimeCode = .ok nativeContract) - (hEnv : - Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment - (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) - (hAgree : - nativeCallDispatcherAgreesWithInterpreter fuel contract tx state - observableSlots nativeContract) : - nativeIRRuntimeAgreesWithInterpreter fuel contract tx state observableSlots := by - apply nativeIRRuntimeAgreesWithInterpreter_of_ok_agree - · exact - (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative_eq_callDispatcher_of_lowerRuntimeContractNative - fuel contract tx state observableSlots nativeContract hFragment hLower hEnv) - · exact hAgree - -/-! ## Layer 3: IR → Yul (Generic) -/ - -/-- Layer 3 function-level preservation: any IR function body produces equivalent -results under IR execution and fuel-based Yul execution. -/ -theorem layer3_function_preserves_semantics - (fn : IRFunction) (selector : Nat) (args : List Nat) (initialState : IRState) : - Compiler.Proofs.YulGeneration.resultsMatch - (execIRFunction fn args initialState) - (interpretYulBodyFromState fn selector - (fn.params.zip args |>.foldl (fun s (p, v) => s.setVar p.name v) initialState) - initialState) := - ir_function_body_equiv fn selector args initialState - -/-! ## Bridging Helpers -/ - -/-- Explicit bridge hypothesis for the param-load erasure step. -/ -private def paramLoadErasure (fn : IRFunction) (tx : IRTransaction) (state : IRState) : Prop := - let paramState := fn.params.zip tx.args |>.foldl - (fun s (p, v) => s.setVar p.name v) state - execYulStmts (yulStateOfIR 0 paramState) fn.body = - execYulStmts (YulState.initial (YulTransaction.ofIR tx) state.storage state.events) fn.body - -/-- Result wrapping equivalence: `interpretYulRuntime` produces the same `YulResult` -as `yulResultOfExecWithRollback` when the rollback storage matches. -/ -theorem interpretYulRuntime_eq_yulResultOfExec - (stmts : List Yul.YulStmt) (tx : YulTransaction) (stor : IRStorageSlot → IRStorageWord) - (events : List (List Nat)) : - interpretYulRuntime stmts tx stor events = - yulResultOfExecWithRollback (YulState.initial tx stor events) - (execYulStmts (YulState.initial tx stor events) stmts) := by - simp [interpretYulRuntime] - cases execYulStmts (YulState.initial tx stor events) stmts with - | «continue» s => simp [yulResultOfExecWithRollback] - | «return» v s => simp [yulResultOfExecWithRollback] - | «stop» s => simp [yulResultOfExecWithRollback] - | «revert» s => simp [yulResultOfExecWithRollback, YulState.initial] - -/-- State equivalence: under the entry-point hypotheses, `yulStateOfIR` produces -the same YulState as `YulState.initial`. -/ -theorem yulStateOfIR_eq_initial - (sel : Nat) (state : IRState) (tx : IRTransaction) - (hcalldata : state.calldata = tx.args) - (hsender : state.sender = tx.sender) - (hmsgValue : state.msgValue = tx.msgValue) - (hthis : state.thisAddress = tx.thisAddress) - (htimestamp : state.blockTimestamp = tx.blockTimestamp) - (hnumber : state.blockNumber = tx.blockNumber) - (hchain : state.chainId = tx.chainId) - (hblobBaseFee : state.blobBaseFee = tx.blobBaseFee) - (hselector : state.selector = tx.functionSelector) - (hreturn : state.returnValue = none) - (hmemory : state.memory = fun _ => 0) - (htransient : state.transientStorage = fun _ => 0) - (hvars : state.vars = []) : - yulStateOfIR sel state = - YulState.initial - { sender := tx.sender - msgValue := tx.msgValue - thisAddress := tx.thisAddress - blockTimestamp := tx.blockTimestamp - blockNumber := tx.blockNumber - chainId := tx.chainId - blobBaseFee := tx.blobBaseFee - functionSelector := tx.functionSelector - args := tx.args } - state.storage state.events := by - simp [yulStateOfIR, YulState.initial, hvars, hmemory, htransient, hcalldata, hsender, hmsgValue, - hthis, htimestamp, hnumber, hchain, hblobBaseFee, hselector, hreturn] - -/-- Hypothesis-driven param-load erasure. -/ -theorem execYulStmts_paramState_eq_emptyVars - (fn : IRFunction) (tx : IRTransaction) (state : IRState) - (_hvars : state.vars = []) - (_hmemory : state.memory = fun _ => 0) - (_hcalldata : state.calldata = tx.args) - (_hsender : state.sender = tx.sender) - (_hmsgValue : state.msgValue = tx.msgValue) - (_hthis : state.thisAddress = tx.thisAddress) - (_htimestamp : state.blockTimestamp = tx.blockTimestamp) - (_hnumber : state.blockNumber = tx.blockNumber) - (_hchain : state.chainId = tx.chainId) - (_hselector : state.selector = tx.functionSelector) - (_hreturn : state.returnValue = none) - (hparamErase : paramLoadErasure fn tx state) : - paramLoadErasure fn tx state := - hparamErase - -/-- Internal function tables are bridged whenever the Layer-3 well-formedness -predicate says they contain only Yul function definitions. The retargeting -bridge treats function-definition nodes as straight-line declarations; the -called-body simulation remains covered by the existing function-body -hypotheses. -/ -private theorem internalFunctions_bridged_of_contractWF - (contract : IRContract) (hWF : ContractWF contract) : - Compiler.Proofs.YulGeneration.Backends.BridgedStmts - contract.internalFunctions := by - intro stmt hMem - rcases hWF stmt hMem with ⟨name, params, rets, body, hStmt⟩ - subst hStmt - exact Compiler.Proofs.YulGeneration.Backends.bridgedStmt_funcDef - name params rets body +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_withSwitchIds_atFuel + (fuel' : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + (cases'.length + 19 ≤ fuel' → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let nativeContract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_withSwitchIds_atFuel_projectResult_eq + fuel' tx.functionSelector reservedNames n0 irContract.functions inner next + functions (YulTransaction.ofIR tx) state.storage state.events materializedSlots + hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨switchStart, cases', midN, hLowerCases, hCont⟩ + refine ⟨switchStart, cases', midN, hLowerCases, ?_⟩ + intro hFuel + rcases hCont hFuel with ⟨hExec, hProject⟩ + unfold nativeDispatcherExecMatchesIRPositive + dsimp [nativeContract, materializedSlots] at hExec hProject ⊢ + rw [hExec, hProject] + simp [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn, + Compiler.Proofs.IRGeneration.interpretIR, hFind] -/-- Convert the new source-level safe-body closure theorem into the low-level -`BridgedStmts fn.body` witness still consumed by the EVMYulLean runtime -retargeting theorem. This is the key local bridge from compiler-produced -`FunctionSpec` bodies to emitted IR function bodies: static scalar parameter -loads are bridged by the prologue theorem, and the compiled source body is -bridged by `compileStmtList_always_bridged`. -/ -theorem compileFunctionSpec_bridged_of_safe_static_params - (fields : List CompilationModel.Field) - (events : List CompilationModel.EventDef) - (errors : List CompilationModel.ErrorDef) - (selector : Nat) (spec : CompilationModel.FunctionSpec) - (irFn : IRFunction) - (hStaticParams : - Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams spec.params) - (hSafeBody : - Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts - fields errors .calldata [] false spec.body) - (hcompile : - CompilationModel.compileFunctionSpec fields events errors [] selector spec = - Except.ok irFn) : - Compiler.Proofs.YulGeneration.Backends.BridgedStmts irFn.body := by - rcases Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_components - fields events errors selector spec irFn hcompile with - ⟨returns, bodyStmts, _hvalidate, _hreturns, hbody, hirFn⟩ - subst irFn - change - Compiler.Proofs.YulGeneration.Backends.BridgedStmts - (CompilationModel.genParamLoads spec.params ++ bodyStmts) - exact Compiler.Proofs.YulGeneration.Backends.BridgedStmts_append - (Compiler.Proofs.YulGeneration.Backends.genParamLoads_static_scalar_bridged - spec.params hStaticParams) - (Compiler.Proofs.YulGeneration.Backends.compileStmtList_always_bridged - fields events errors .calldata [] false spec.body - (spec.params.map (·.name)) hSafeBody hbody) +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive + (fuel : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 19) + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq + fuel tx.functionSelector irContract.functions fn inner functions + (YulTransaction.ofIR tx) state.storage state.events materializedSlots + err nativeYul hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hBody hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err := by + simpa [materializedSlots] using hBody + rcases hCont hBody' hProject with ⟨hExec, hProject'⟩ + exact nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + hExec hProject' hMatch -/-- Lift the one-function bridge closure theorem across the compiled external -function table. This keeps the public EndToEnd theorem from exposing raw -`BridgedStmts fn.body` obligations when callers already have source-level -safe-body/static-param witnesses for every selector-dispatched function. -/ -theorem compiledExternalFunctions_bridged_of_safe_static - (fields : List CompilationModel.Field) - (events : List CompilationModel.EventDef) - (errors : List CompilationModel.ErrorDef) : - ∀ {entries : List (CompilationModel.FunctionSpec × Nat)} - {irFns : List IRFunction}, - List.Forall₂ - (fun entry irFn => - CompilationModel.compileFunctionSpec fields events errors - [] entry.2 entry.1 = Except.ok irFn) - entries irFns → - (∀ entry, entry ∈ entries → - Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams - entry.1.params) → - (∀ entry, entry ∈ entries → - Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts - fields errors .calldata [] false entry.1.body) → - ∀ irFn, irFn ∈ irFns → - Compiler.Proofs.YulGeneration.Backends.BridgedStmts irFn.body := by - intro entries irFns hcompiled hStatic hSafe - induction hcompiled with - | nil => - intro irFn hmem - cases hmem - | @cons entry irFn entries irFns hhead htail ih => - intro target hmem - simp only [List.mem_cons] at hmem - rcases hmem with rfl | hmemTail - · exact compileFunctionSpec_bridged_of_safe_static_params - fields events errors entry.2 entry.1 target - (hStatic entry (by simp)) - (hSafe entry (by simp)) - hhead - · exact ih - (fun next hnext => hStatic next (by simp [hnext])) - (fun next hnext => hSafe next (by simp [hnext])) - target hmemTail +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_atFuel + (fuel' : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + (cases'.length + 19 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_atFuel_projectResult_eq + fuel' tx.functionSelector irContract.functions fn inner functions + (YulTransaction.ofIR tx) state.storage state.events materializedSlots + err nativeYul hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro hFuel hBody hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err := by + simpa [materializedSlots] using hBody + rcases hCont hFuel hBody' hProject with ⟨hExec, hProject'⟩ + exact nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + hExec hProject' hMatch -/-- Bridging: the two Yul execution entry points produce the same result -when the IR state has empty vars and zero memory. -/ -theorem yulBody_from_state_eq_yulBody - (fn : IRFunction) (tx : IRTransaction) (state : IRState) - (hcalldata : state.calldata = tx.args) - (hsender : state.sender = tx.sender) - (hmsgValue : state.msgValue = tx.msgValue) - (hthis : state.thisAddress = tx.thisAddress) - (htimestamp : state.blockTimestamp = tx.blockTimestamp) - (hnumber : state.blockNumber = tx.blockNumber) - (hchain : state.chainId = tx.chainId) - (hblobBaseFee : state.blobBaseFee = tx.blobBaseFee) - (hselector : state.selector = tx.functionSelector) - (hreturn : state.returnValue = none) - (hmemory : state.memory = fun _ => 0) - (htransient : state.transientStorage = fun _ => 0) - (hvars : state.vars = []) - (hparamErase : paramLoadErasure fn tx state) : - Compiler.Proofs.YulGeneration.resultsMatch - (execIRFunction fn tx.args state) - (interpretYulBody fn tx state) := by - have h_ir_from := ir_function_body_equiv fn 0 tx.args state - suffices h_eq : interpretYulBodyFromState fn 0 - (fn.params.zip tx.args |>.foldl (fun s (p, v) => s.setVar p.name v) state) - state = interpretYulBody fn tx state by - rwa [h_eq] at h_ir_from - simp only [interpretYulBodyFromState, interpretYulBody] - have h_rollback := yulStateOfIR_eq_initial 0 state tx hcalldata hsender hmsgValue hthis htimestamp hnumber hchain hblobBaseFee hselector hreturn hmemory htransient hvars - have h_exec := execYulStmts_paramState_eq_emptyVars fn tx state hvars hmemory hcalldata hsender hmsgValue hthis htimestamp hnumber hchain hselector hreturn hparamErase - rw [h_rollback] - simp only at h_exec - rw [h_exec] - exact (interpretYulRuntime_eq_yulResultOfExec fn.body - (YulTransaction.ofIR tx) state.storage state.events).symm - -/-! ## Layer 3 Contract-Level: IR → Yul (via runtime dispatch) -/ - -/-- Layer 3 contract-level preservation: an IR contract execution produces -equivalent results under the Yul runtime dispatch. -/ -theorem layer3_contract_preserves_semantics - (contract : IRContract) (tx : IRTransaction) (initialState : IRState) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hparamErase : ∀ fn, fn ∈ contract.functions → paramLoadErasure fn tx (initialState.withTx tx)) - (hdispatchGuardSafe : ∀ fn, fn ∈ contract.functions → DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ contract.functions → yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ contract.functions → HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ contract.functions → - yulStmtsLoopFree fn.body = true) - (hWF : ContractWF contract) - (hNoFallback : contract.fallbackEntrypoint = none) - (hNoReceive : contract.receiveEntrypoint = none) : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR contract tx initialState) - (interpretYulFromIR contract tx initialState) := by - apply yulCodegen_preserves_semantics contract tx initialState - hselector hNoWrap hWF hNoFallback hNoReceive hdispatchGuardSafe hNoHasSelector hHasSelectorDead - hLoopFree - · intro fn hmem - exact (yulBody_from_state_eq_yulBody fn tx (initialState.withTx tx) - rfl rfl rfl rfl rfl rfl rfl rfl rfl - (by simpa using hreturn) - (by simpa using hmemory) - (by simpa using htransient) - (by simpa using hvars) - (hparamErase fn hmem)) - -/-- Reference-oracle version: delegates directly to the historical -`execYulFuel`-backed `yulCodegen_preserves_semantics` theorem. -/ -theorem layer3_contract_preserves_semantics_via_reference_oracle - (contract : IRContract) (tx : IRTransaction) (initialState : IRState) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hWF : ContractWF contract) - (hNoFallback : contract.fallbackEntrypoint = none) - (hNoReceive : contract.receiveEntrypoint = none) - (hdispatchGuardSafe : ∀ fn, fn ∈ contract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ contract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ contract.functions → - HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ contract.functions → - yulStmtsLoopFree fn.body = true) - (hbody : ∀ fn, fn ∈ contract.functions → - Compiler.Proofs.YulGeneration.resultsMatch - (execIRFunction fn tx.args (initialState.withTx tx)) - (interpretYulBody fn tx (initialState.withTx tx))) : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR contract tx initialState) - (interpretYulFromIR contract tx initialState) := - yulCodegen_preserves_semantics contract tx initialState - hselector hNoWrap hWF hNoFallback hNoReceive hdispatchGuardSafe hNoHasSelector hHasSelectorDead - hLoopFree hbody - -/-! ## Layer 3 Contract-Level: IR → EVMYulLean-backed Yul -/ - -/-- Lower-level Layer 3 contract-level preservation targeting the -EVMYulLean-backed Yul runtime. This is the EndToEnd-facing wrapper around -`yulCodegen_preserves_semantics_evmYulLean`; callers supply the existing -function-body simulation hypotheses plus `BridgedStmts` witnesses for emitted -external function bodies. Fallback/receive witnesses are discharged from the -existing `none` hypotheses, and the internal-function table witness is derived -from `ContractWF`. -/ -theorem layer3_contract_preserves_semantics_evmYulLean_with_function_bridge - (contract : IRContract) (tx : IRTransaction) (initialState : IRState) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hWF : ContractWF contract) - (hNoFallback : contract.fallbackEntrypoint = none) - (hNoReceive : contract.receiveEntrypoint = none) - (hdispatchGuardSafe : ∀ fn, fn ∈ contract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ contract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ contract.functions → - HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ contract.functions → - yulStmtsLoopFree fn.body = true) - (hbody : ∀ fn, fn ∈ contract.functions → - Compiler.Proofs.YulGeneration.resultsMatch - (execIRFunction fn tx.args (initialState.withTx tx)) - (interpretYulBody fn tx (initialState.withTx tx))) - (hFunctions : ∀ fn, fn ∈ contract.functions → - Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body) : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR contract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend - .evmYulLean (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := - Compiler.Proofs.YulGeneration.Backends.yulCodegen_preserves_semantics_evmYulLean - contract tx initialState hselector hNoWrap hWF hNoFallback hNoReceive - hdispatchGuardSafe hNoHasSelector hHasSelectorDead hLoopFree hbody - hFunctions - (by intro fb hSome; rw [hNoFallback] at hSome; cases hSome) - (by intro rc hSome; rw [hNoReceive] at hSome; cases hSome) - (internalFunctions_bridged_of_contractWF contract hWF) - -/-- Layer 3 contract-level preservation targeting EVMYulLean under explicit -function-body bridge witnesses, using the same entry-state normalization hypotheses as -`layer3_contract_preserves_semantics`. -/ -theorem layer3_contract_preserves_semantics_evmYulLean - (contract : IRContract) (tx : IRTransaction) (initialState : IRState) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hparamErase : ∀ fn, fn ∈ contract.functions → paramLoadErasure fn tx (initialState.withTx tx)) - (hdispatchGuardSafe : ∀ fn, fn ∈ contract.functions → DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ contract.functions → yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ contract.functions → HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ contract.functions → - yulStmtsLoopFree fn.body = true) - (hWF : ContractWF contract) - (hNoFallback : contract.fallbackEntrypoint = none) - (hNoReceive : contract.receiveEntrypoint = none) - (hFunctions : ∀ fn, fn ∈ contract.functions → - Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body) : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR contract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend - .evmYulLean (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := by - apply layer3_contract_preserves_semantics_evmYulLean_with_function_bridge contract tx initialState - hselector hNoWrap hWF hNoFallback hNoReceive hdispatchGuardSafe hNoHasSelector - hHasSelectorDead hLoopFree - · intro fn hmem - exact (yulBody_from_state_eq_yulBody fn tx (initialState.withTx tx) - rfl rfl rfl rfl rfl rfl rfl rfl rfl - (by simpa using hreturn) - (by simpa using hmemory) - (by simpa using htransient) - (by simpa using hvars) - (hparamErase fn hmem)) - · exact hFunctions - -/-- Native Layer 3 bridge theorem under the named generated-fragment bridge obligation. -/ -theorem layer3_contract_preserves_semantics_native_of_interpreter_bridge - (fuel : Nat) (contract : IRContract) (tx : IRTransaction) - (initialState : IRState) (observableSlots : List Nat) - (hselector : tx.functionSelector < selectorModulus) (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) (hreturn : initialState.returnValue = none) - (hparamErase : ∀ fn, fn ∈ contract.functions → paramLoadErasure fn tx (initialState.withTx tx)) - (hdispatchGuardSafe : ∀ fn, fn ∈ contract.functions → DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ contract.functions → yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ contract.functions → HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ contract.functions → yulStmtsLoopFree fn.body = true) - (hWF : ContractWF contract) (hNoFallback : contract.fallbackEntrypoint = none) - (hNoReceive : contract.receiveEntrypoint = none) - (hFunctions : ∀ fn, fn ∈ contract.functions → Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body) - (hFuel : fuel = sizeOf (Compiler.emitYul contract).runtimeCode + 1) - (hNativeBridge : nativeIRRuntimeAgreesWithInterpreter fuel contract tx initialState observableSlots) : - nativeResultsMatchOn observableSlots (interpretIR contract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative - fuel contract tx initialState observableSlots) := by - subst fuel - have hLayer := - layer3_contract_preserves_semantics_evmYulLean contract tx initialState - hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead hLoopFree hWF hNoFallback - hNoReceive hFunctions - unfold nativeIRRuntimeAgreesWithInterpreter at hNativeBridge - cases hNative : - Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative - (sizeOf (Compiler.emitYul contract).runtimeCode + 1) - contract tx initialState observableSlots with - | error err => - rw [hNative] at hNativeBridge - exact False.elim hNativeBridge - | ok native => - rw [hNative] at hNativeBridge - exact nativeResultsMatchOn_ok_of_resultsMatch_of_yulResultsAgreeOn hLayer - hNativeBridge - -/-- Native Layer 3 bridge theorem with the remaining obligation stated at the -concrete lowered EVMYulLean contract boundary. - -This variant removes the opaque `nativeIRRuntimeAgreesWithInterpreter` -hypothesis from callers. They instead prove native lowering succeeds, the -selected native runtime path has representable environment reads, and projected -`callDispatcher` execution agrees with the interpreter oracle. -/ -theorem layer3_contract_preserves_semantics_native_of_lowered_callDispatcher_bridge - (fuel : Nat) (contract : IRContract) (tx : IRTransaction) - (initialState : IRState) (observableSlots : List Nat) - (nativeContract : EvmYul.Yul.Ast.YulContract) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hparamErase : ∀ fn, fn ∈ contract.functions → paramLoadErasure fn tx (initialState.withTx tx)) - (hdispatchGuardSafe : ∀ fn, fn ∈ contract.functions → DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ contract.functions → yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ contract.functions → HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ contract.functions → yulStmtsLoopFree fn.body = true) - (hWF : ContractWF contract) (hNoFallback : contract.fallbackEntrypoint = none) - (hNoReceive : contract.receiveEntrypoint = none) - (hFunctions : ∀ fn, fn ∈ contract.functions → - Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body) - (hFuel : fuel = sizeOf (Compiler.emitYul contract).runtimeCode + 1) - (hFragment : - Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment - (Compiler.emitYul contract).runtimeCode = true) +/-- Artifact-fixed selector-hit error dispatcher bridge for the no-reserved +generated dispatcher lowering path. + +This is the no-mapping companion to the reserved-context artifact theorem +below: artifacts are exposed first, while `err/nativeYul` remain quantified in +the returned continuation. -/ +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_atFuel_artifact + (fuel' : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (hLower : - Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative - (Compiler.emitYul contract).runtimeCode = .ok nativeContract) - (hEnv : - Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment - (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) - (hNativeCallDispatcher : - nativeCallDispatcherAgreesWithInterpreter fuel contract tx initialState - observableSlots nativeContract) : - nativeResultsMatchOn observableSlots (interpretIR contract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative - fuel contract tx initialState observableSlots) := - layer3_contract_preserves_semantics_native_of_interpreter_bridge - fuel contract tx initialState observableSlots - hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead hLoopFree hWF hNoFallback - hNoReceive hFunctions hFuel - (nativeIRRuntimeAgreesWithInterpreter_of_lowered_callDispatcher_agree - hFragment hLower hEnv hNativeCallDispatcher) + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + (∀ (err : EvmYul.Yul.Exception) (nativeYul : YulResult), + cases'.length + 19 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_atFuel_artifact_projectResult_eq + fuel' tx.functionSelector irContract.functions fn inner functions + (YulTransaction.ofIR tx) state.storage state.events materializedSlots + hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro err nativeYul hFuel hBody hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err := by + simpa [materializedSlots] using hBody + rcases hCont err nativeYul hFuel hBody' hProject with ⟨hExec, hProject'⟩ + exact nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + hExec hProject' hMatch -/-! ## Layers 2+3 Composition -/ +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds + (fuel : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 19) + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_projectResult_eq + fuel tx.functionSelector reservedNames n0 irContract.functions fn inner next + functions (YulTransaction.ofIR tx) state.storage state.events + materializedSlots err nativeYul hLower hSelector hFind hNoWrap + hSelectorRangeNative hFunctionSelectorsRange with + ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hBody hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err := by + simpa [materializedSlots] using hBody + rcases hCont hBody' hProject with ⟨hExec, hProject'⟩ + exact nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + hExec hProject' hMatch -/-- Reference-oracle end-to-end wrapper: given a successfully compiled -contract, IR execution matches the historical Verity-backed Yul execution -target. The EVMYulLean-backed theorem below is the authoritative safe-body -target after the Phase 4 retarget. -/ -theorem layers2_3_ir_matches_yul_via_reference_oracle - (spec : CompilationModel.CompilationModel) (selectors : List Nat) - (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) - (_hCompile : CompilationModel.compile spec selectors = .ok irContract) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hparamErase : ∀ fn, fn ∈ irContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) - (hdispatchGuardSafe : ∀ fn, fn ∈ irContract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ irContract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ irContract.functions → - HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ irContract.functions → - yulStmtsLoopFree fn.body = true) - (hWF : ContractWF irContract) - (hNoFallback : irContract.fallbackEntrypoint = none) - (hNoReceive : irContract.receiveEntrypoint = none) : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR irContract tx initialState) - (interpretYulFromIR irContract tx initialState) := - layer3_contract_preserves_semantics irContract tx initialState - hselector hNoWrap hvars hmemory htransient hreturn hparamErase hdispatchGuardSafe hNoHasSelector - hHasSelectorDead hLoopFree hWF hNoFallback hNoReceive - -/-- End-to-end bridge-witness variant: given a successfully compiled contract, -IR execution matches EVMYulLean-backed Yul execution under explicit -function-body closure hypotheses. Fallback/receive bridge witnesses are -vacuous under the public `none` hypotheses and are discharged internally, as is -the internal function table witness via `ContractWF`. -/ -theorem layers2_3_ir_matches_yul_evmYulLean_with_function_bridge - (spec : CompilationModel.CompilationModel) (selectors : List Nat) - (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) - (_hCompile : CompilationModel.compile spec selectors = .ok irContract) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hparamErase : ∀ fn, fn ∈ irContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) - (hdispatchGuardSafe : ∀ fn, fn ∈ irContract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ irContract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ irContract.functions → - HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ irContract.functions → - yulStmtsLoopFree fn.body = true) - (hWF : ContractWF irContract) - (hNoFallback : irContract.fallbackEntrypoint = none) - (hNoReceive : irContract.receiveEntrypoint = none) - (hFunctions : ∀ fn, fn ∈ irContract.functions → - Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body) : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR irContract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend - .evmYulLean (Compiler.emitYul irContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := - layer3_contract_preserves_semantics_evmYulLean irContract tx initialState - hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead hLoopFree hWF hNoFallback - hNoReceive hFunctions - -/-- End-to-end: for a supported compiler-produced contract whose -selector-dispatched function bodies are in the EVMYulLean-safe source fragment -and whose ABI parameters compile through the static-scalar prologue bridge, IR -execution matches EVMYulLean-backed Yul execution without exposing a raw -`BridgedStmts fn.body` hypothesis to callers. -/ -theorem layers2_3_ir_matches_yul_evmYulLean - (spec : CompilationModel.CompilationModel) (selectors : List Nat) - (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) - (hCompile : CompilationModel.compile spec selectors = .ok irContract) - (hSupported : SupportedSpec spec selectors) - (hStaticParams : - ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → - Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams - entry.1.params) - (hSafeBodies : - ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → - Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts - spec.fields spec.errors .calldata [] false entry.1.body) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hparamErase : ∀ fn, fn ∈ irContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) - (hdispatchGuardSafe : ∀ fn, fn ∈ irContract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ irContract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ irContract.functions → - HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ irContract.functions → - yulStmtsLoopFree fn.body = true) - (hWF : ContractWF irContract) - (hNoFallback : irContract.fallbackEntrypoint = none) - (hNoReceive : irContract.receiveEntrypoint = none) : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR irContract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend - .evmYulLean (Compiler.emitYul irContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := - layers2_3_ir_matches_yul_evmYulLean_with_function_bridge - spec selectors irContract tx initialState - hCompile hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead hLoopFree hWF hNoFallback - hNoReceive - (compiledExternalFunctions_bridged_of_safe_static - spec.fields spec.events spec.errors - (Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions - spec selectors hSupported irContract hCompile) - hStaticParams hSafeBodies) +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds_atFuel + (fuel' : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + (cases'.length + 19 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_atFuel_projectResult_eq + fuel' tx.functionSelector reservedNames n0 irContract.functions fn inner + next functions (YulTransaction.ofIR tx) state.storage state.events + materializedSlots err nativeYul hLower hSelector hFind hNoWrap + hSelectorRangeNative hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro hFuel hBody hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err := by + simpa [materializedSlots] using hBody + rcases hCont hFuel hBody' hProject with ⟨hExec, hProject'⟩ + exact nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + hExec hProject' hMatch -/-- Native end-to-end theorem seam for supported compiler-produced contracts. +/-- Artifact-fixed reserved-context selector-hit error dispatcher bridge. -The conclusion targets `Native.interpretIRRuntimeNative` directly. The remaining -generated-fragment proof obligation is exactly -`nativeIRRuntimeAgreesWithInterpreter`: native EVMYulLean execution of the -emitted runtime code must agree with the current EVMYulLean-backed interpreter -oracle for the same fuel, transaction, initial storage/events, and observable -storage-slot materialization. -/ -theorem layers2_3_ir_matches_native_evmYulLean_of_interpreter_bridge - (fuel : Nat) - (spec : CompilationModel.CompilationModel) (selectors : List Nat) +Unlike +`nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds_atFuel`, +this exposes the selected case artifacts before the concrete error/result pair +is chosen. Halt-style successful bodies can therefore run first, produce their +`YulHalt` state, and then feed that error into the returned continuation. -/ +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds_atFuel_artifact + (fuel' : Nat) (reservedNames : List String) (n0 : Nat) (irContract : IRContract) (tx : IRTransaction) - (initialState : IRState) (observableSlots : List Nat) - (hCompile : CompilationModel.compile spec selectors = .ok irContract) - (hSupported : SupportedSpec spec selectors) - (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → - Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) - (hSafeBodies : - ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → - Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts spec.fields - spec.errors .calldata [] false entry.1.body) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hparamErase : ∀ fn, fn ∈ irContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) - (hdispatchGuardSafe : ∀ fn, fn ∈ irContract.functions → DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ irContract.functions → yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ irContract.functions → HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ irContract.functions → yulStmtsLoopFree fn.body = true) - (hWF : ContractWF irContract) (hNoFallback : irContract.fallbackEntrypoint = none) - (hNoReceive : irContract.receiveEntrypoint = none) - (hFuel : fuel = sizeOf (Compiler.emitYul irContract).runtimeCode + 1) - (hNativeBridge : nativeIRRuntimeAgreesWithInterpreter fuel irContract tx - initialState observableSlots) : - nativeResultsMatchOn observableSlots - (interpretIR irContract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative - fuel irContract tx initialState observableSlots) := - layer3_contract_preserves_semantics_native_of_interpreter_bridge - fuel irContract tx initialState observableSlots - hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead hLoopFree hWF hNoFallback - hNoReceive - (compiledExternalFunctions_bridged_of_safe_static - spec.fields spec.events spec.errors - (Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions - spec selectors hSupported irContract hCompile) - hStaticParams hSafeBodies) - hFuel - hNativeBridge - -/-- Supported compiler-produced native theorem seam with the remaining native -obligation exposed at the concrete lowered `callDispatcher` boundary. -/ -theorem layers2_3_ir_matches_native_evmYulLean_of_lowered_callDispatcher_bridge - (fuel : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) - (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) - (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) - (hCompile : CompilationModel.compile spec selectors = .ok irContract) - (hSupported : SupportedSpec spec selectors) - (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) - (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → - Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts spec.fields spec.errors .calldata [] false entry.1.body) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hparamErase : ∀ fn, fn ∈ irContract.functions → paramLoadErasure fn tx (initialState.withTx tx)) - (hdispatchGuardSafe : ∀ fn, fn ∈ irContract.functions → DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ irContract.functions → yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ irContract.functions → HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ irContract.functions → yulStmtsLoopFree fn.body = true) - (hWF : ContractWF irContract) (hNoFallback : irContract.fallbackEntrypoint = none) - (hNoReceive : irContract.receiveEntrypoint = none) - (hFuel : fuel = sizeOf (Compiler.emitYul irContract).runtimeCode + 1) - (hFragment : - Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment - (Compiler.emitYul irContract).runtimeCode = true) - (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative - (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) - (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment - (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) - (hNativeCallDispatcher : nativeCallDispatcherAgreesWithInterpreter fuel irContract tx initialState observableSlots nativeContract) : - nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative - fuel irContract tx initialState observableSlots) := - layer3_contract_preserves_semantics_native_of_lowered_callDispatcher_bridge - fuel irContract tx initialState observableSlots nativeContract - hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead hLoopFree hWF hNoFallback - hNoReceive - (compiledExternalFunctions_bridged_of_safe_static - spec.fields spec.events spec.errors - (Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions - spec selectors hSupported irContract hCompile) - hStaticParams hSafeBodies) - hFuel hFragment hLower hEnv hNativeCallDispatcher + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + (∀ (err : EvmYul.Yul.Exception) (nativeYul : YulResult), + cases'.length + 19 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_atFuel_artifact_projectResult_eq + fuel' tx.functionSelector reservedNames n0 irContract.functions fn inner + next functions (YulTransaction.ofIR tx) state.storage state.events + materializedSlots hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro err nativeYul hFuel hBody hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err := by + simpa [materializedSlots] using hBody + rcases hCont err nativeYul hFuel hBody' hProject with ⟨hExec, hProject'⟩ + exact nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + hExec hProject' hMatch -/-! ## Concrete Instantiation: SimpleStorage -/ +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive + (fuel : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 19) + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_projectResult_eq_preserved + fuel tx.functionSelector irContract.functions fn inner functions + (YulTransaction.ofIR tx) state.storage state.events materializedSlots + final nativeYulRaw hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hBody' hPreservesMatched rfl with ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -/-- SimpleStorage end-to-end: compile → IR → Yul preserves semantics. -/ -theorem simpleStorage_endToEnd - (tx : IRTransaction) (initialState : IRState) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hdispatchGuardSafe : ∀ fn, fn ∈ simpleStorageIRContract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ simpleStorageIRContract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ simpleStorageIRContract.functions → - HasSelectorDeadBridge fn.body) - (hparamErase : ∀ fn, fn ∈ simpleStorageIRContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR simpleStorageIRContract tx initialState) - (interpretYulFromIR simpleStorageIRContract tx initialState) := - layer3_contract_preserves_semantics simpleStorageIRContract tx initialState - hselector hNoWrap hvars hmemory htransient hreturn hparamErase hdispatchGuardSafe hNoHasSelector - hHasSelectorDead - (by intro fn hmem; simp [simpleStorageIRContract] at hmem ⊢; rcases hmem with rfl | rfl <;> rfl) - (by intro s hs; simp [simpleStorageIRContract] at hs) rfl rfl +/-- Generated-prefix variant of +`nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive` +for payable functions. The selected-body execution and matched-flag +preservation premises are over the lowered user body `fn.body`, not the whole +generated selector case body. -/ +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_generated_prefix + (fuel : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 23) + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_generated_prefix_projectResult_eq + fuel tx.functionSelector irContract.functions fn inner functions tx + state.storage state.events materializedSlots final nativeYulRaw hLower + hSelector hFind hNoWrap hSelectorRangeNative hFunctionSelectorsRange + hPayable hguards hArgs with + ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hBody' hPreservesMatched rfl with ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -/-- The concrete SimpleStorage IR fixture uses only EVMYulLean-bridged Yul -shapes: calldata parameter loading, one literal-slot storage write, one memory -write from `sload`, and `stop`/`return` terminators. -/ -private theorem simpleStorage_functions_bridged : - ∀ fn, fn ∈ simpleStorageIRContract.functions → - Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body := by - intro fn hmem - simp [simpleStorageIRContract] at hmem - rcases hmem with rfl | rfl - · apply Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_let - · exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.call - "calldataload" [Yul.YulExpr.lit 4] - (by - left - simp [Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins]) - (by - intro arg harg - simp at harg - subst arg - exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit 4) - · apply Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_sstore_lit - · exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.ident "value" - · exact Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_stop - · apply Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_mstore - · exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit 0 - · exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.call - "sload" [Yul.YulExpr.lit 0] - (by - left - simp [Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins]) - (by - intro arg harg - simp at harg - subst arg - exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit 0) - · exact Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_return - (Yul.YulExpr.lit 0) (Yul.YulExpr.lit 32) - (Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit 0) - (Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit 32) +/-- Generated-prefix variant of +`nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive` +for non-payable functions. The selected-body execution and matched-flag +preservation premises are over the lowered user body `fn.body`, not the whole +generated selector case body. -/ +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_generated_prefix + (fuel : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 24) + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_generated_prefix_projectResult_eq + fuel tx.functionSelector irContract.functions fn inner functions tx + state.storage state.events materializedSlots final nativeYulRaw hLower + hSelector hFind hNoWrap hSelectorRangeNative hFunctionSelectorsRange + hNonPayable hguards hArgs with + ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hBody' hPreservesMatched rfl with ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -/-- The emitted SimpleStorage runtime consists of the single generated external -dispatcher shell for the two concrete SimpleStorage functions. +/-- Exact-total-fuel generated-prefix variant for payable functions. The +selected-body execution and matched-flag preservation premises are over the +lowered user body `fn.body`, while the native dispatcher package is stated at +the externally supplied `fuel'`. -/ +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_generated_prefix_atFuel + (fuel' : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 23 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_generated_prefix_atFuel_projectResult_eq + fuel' tx.functionSelector irContract.functions fn inner functions tx + state.storage state.events materializedSlots final nativeYulRaw hLower + hSelector hFind hNoWrap hSelectorRangeNative hFunctionSelectorsRange + hPayable hguards hArgs with + ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hFuel hBody' hPreservesMatched rfl with + ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -This pins down the outer runtime layer that the native dispatcher bridge must -peel before applying the concrete lowered selector-switch lemmas. -/ -theorem simpleStorage_runtimeCode_eq_single_dispatcher : - (Compiler.emitYul simpleStorageIRContract).runtimeCode = - [Compiler.CodegenCommon.buildSwitch - simpleStorageIRContract.functions none none] := by - dsimp [Compiler.emitYul, Compiler.CodegenCommon.emitYul, - Compiler.runtimeCode, Compiler.CodegenCommon.runtimeCode, - simpleStorageIRContract] +/-- Exact-total-fuel generated-prefix variant for non-payable functions. The +selected-body execution and matched-flag preservation premises are over the +lowered user body `fn.body`, while the native dispatcher package is stated at +the externally supplied `fuel'`. -/ +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_generated_prefix_atFuel + (fuel' : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 24 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_generated_prefix_atFuel_projectResult_eq + fuel' tx.functionSelector irContract.functions fn inner functions tx + state.storage state.events materializedSlots final nativeYulRaw hLower + hSelector hFind hNoWrap hSelectorRangeNative hFunctionSelectorsRange + hNonPayable hguards hArgs with + ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hFuel hBody' hPreservesMatched rfl with + ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -theorem lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative - (stmt : Yul.YulStmt) - (hNoFunc : ∀ name params rets body, - stmt ≠ Yul.YulStmt.funcDef name params rets body) : - Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative [stmt] = - match Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative [stmt] with - | .ok dispatcher => - .ok { dispatcher := .Block dispatcher - functions := - (∅ : - Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) } - | .error err => .error err := by - unfold Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative - unfold Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative - dsimp - rw [Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNativeAux_stmt_cons] - · rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons] - cases hLower : - Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds - (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames [stmt]) - 0 stmt with - | ok pair => - cases pair with - | mk lowered next => - simp [Bind.bind, Except.bind, Pure.pure, Except.pure, - Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNativeAux] - | error err => - simp [Bind.bind, Except.bind] - · exact hNoFunc +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_atFuel + (fuel' : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + (cases'.length + 19 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_atFuel_projectResult_eq_preserved + fuel' tx.functionSelector irContract.functions fn inner functions + (YulTransaction.ofIR tx) state.storage state.events materializedSlots + final nativeYulRaw hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro hFuel hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hFuel hBody' hPreservesMatched rfl with ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -noncomputable def simpleStorageNativeDispatcherStmts : - List EvmYul.Yul.Ast.Stmt := - match - Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative - [Compiler.CodegenCommon.buildSwitch - simpleStorageIRContract.functions none none] with - | .ok stmts => stmts - | .error _ => [] +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_atFuel_forall + (fuel' : Nat) (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + (∀ final nativeYul, + cases'.length + 19 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_atFuel_projectResult_eq_preserved_forall + fuel' tx.functionSelector irContract.functions fn inner functions + (YulTransaction.ofIR tx) state.storage state.events materializedSlots + hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro final nativeYul hFuel hBody hPreservesMatched hProject hMatch + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont final nativeYulRaw hFuel hBody' hPreservesMatched rfl with + ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -/-- The executable SimpleStorage native witness is exactly the statement -lowering of the single emitted dispatcher shell. +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds + (fuel : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) body' + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 19) + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_projectResult_eq_preserved + fuel tx.functionSelector reservedNames n0 irContract.functions fn inner next + functions (YulTransaction.ofIR tx) state.storage state.events + materializedSlots final nativeYulRaw hLower hSelector hFind hNoWrap + hSelectorRangeNative hFunctionSelectorsRange with + ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hBody' hPreservesMatched rfl with ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -This exposes the concrete lowered dispatcher block without unfolding the -computed native witness in later selector-case proofs. -/ -theorem simpleStorageNativeContract_dispatcher_eq_lowered_stmts : - Compiler.SimpleStorageNativeWitness.nativeContract.dispatcher = - .Block simpleStorageNativeDispatcherStmts := by - unfold Compiler.SimpleStorageNativeWitness.nativeContract - rw [simpleStorage_runtimeCode_eq_single_dispatcher] - rw [lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative] - · cases hLower : - Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative - [Compiler.CodegenCommon.buildSwitch - simpleStorageIRContract.functions none none] with - | ok stmts => - simp [simpleStorageNativeDispatcherStmts, hLower] - | error err => - simp [simpleStorageNativeDispatcherStmts, hLower] - · intro name params rets body h - cases h +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_withSwitchIds_generated_prefix + (fuel : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 23) + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_withSwitchIds_generated_prefix_projectResult_eq + fuel tx.functionSelector reservedNames n0 irContract.functions fn inner + next functions tx state.storage state.events materializedSlots final + nativeYulRaw hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange hPayable hguards hArgs with + ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hBody' hPreservesMatched rfl with ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -/-- A `.block` head in the native lowering surfaces as a singleton `.Block` -output when the lowering succeeds. +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_withSwitchIds_generated_prefix + (fuel : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 24) + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_withSwitchIds_generated_prefix_projectResult_eq + fuel tx.functionSelector reservedNames n0 irContract.functions fn inner + next functions tx state.storage state.events materializedSlots final + nativeYulRaw hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange hNonPayable hguards hArgs with + ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hBody' hPreservesMatched rfl with ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -This is the structural lemma that lets the SimpleStorage native dispatcher -bridge be peeled past its outer block wrapper without unfolding `buildSwitch`. --/ -theorem lowerStmtsNative_single_block_ok_singleton - (stmts : List Yul.YulStmt) - (lowered : List EvmYul.Yul.Ast.Stmt) - (h : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative - [Yul.YulStmt.block stmts] = .ok lowered) : - ∃ inner, lowered = [.Block inner] := by - unfold Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative at h - dsimp at h - rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons] at h - rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_block] at h - cases hInner : +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_withSwitchIds_generated_prefix_atFuel + (fuel' : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames - [Yul.YulStmt.block stmts]) - 0 stmts with - | error err => - rw [hInner] at h - simp only [Bind.bind, Except.bind, reduceCtorEq] at h - | ok pair => - cases pair with - | mk inner next => - rw [hInner] at h - simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, - Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, - List.append_nil, Except.ok.injEq] at h - exact ⟨inner, h.symm⟩ - -/-- The `simpleStorageNativeDispatcherStmts` lowering succeeds and equals the -SimpleStorage native witness dispatcher contents. - -The outer success is inherited from -`Compiler.SimpleStorageNativeWitness.lowerRuntimeContractNative_eq` (which -itself uses the existing `native_decide` trust chain on the runtime witness), -combined with the structural single-statement equation. -/ -theorem simpleStorageNativeDispatcherStmts_lowering_ok : - Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative - [Compiler.CodegenCommon.buildSwitch - simpleStorageIRContract.functions none none] = - .ok simpleStorageNativeDispatcherStmts := by - have hOuter := Compiler.SimpleStorageNativeWitness.lowerRuntimeContractNative_eq - rw [simpleStorage_runtimeCode_eq_single_dispatcher] at hOuter - rw [lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative] at hOuter - · cases hL : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative - [Compiler.CodegenCommon.buildSwitch - simpleStorageIRContract.functions none none] with - | ok stmts => - simp [simpleStorageNativeDispatcherStmts, hL] - | error err => - rw [hL] at hOuter - simp at hOuter - · intro name params rets body h' - cases h' - -/-- The SimpleStorage native dispatcher statement list is a singleton `.Block`. - -Reason: `buildSwitch` produces a `Yul.YulStmt.block`, which the native lowering -maps to `[.Block inner]` for the lowered inner statements. Combined with the -fact that the lowering succeeds (above), this exposes the inner block shape -without further computation. -/ -theorem simpleStorageNativeDispatcherStmts_exists_singleton_block : - ∃ inner : List EvmYul.Yul.Ast.Stmt, - simpleStorageNativeDispatcherStmts = [.Block inner] := by - have hOk := simpleStorageNativeDispatcherStmts_lowering_ok - -- buildSwitch produces a YulStmt.block by definition. - have hBlock : - Compiler.CodegenCommon.buildSwitch - simpleStorageIRContract.functions none none = - Yul.YulStmt.block _ := rfl - rw [hBlock] at hOk - exact lowerStmtsNative_single_block_ok_singleton _ _ hOk - -noncomputable def simpleStorageNativeDispatcherInnerStmts : - List EvmYul.Yul.Ast.Stmt := - Classical.choose simpleStorageNativeDispatcherStmts_exists_singleton_block - -theorem simpleStorageNativeDispatcherStmts_eq_singleton_block : - simpleStorageNativeDispatcherStmts = - [.Block simpleStorageNativeDispatcherInnerStmts] := - Classical.choose_spec simpleStorageNativeDispatcherStmts_exists_singleton_block - -/-- Transitive form of the SimpleStorage native dispatcher shape: combining -the lowered-stmts and singleton-block equalities exposes the dispatcher value -as `.Block [.Block ]`, which is the exact shape consumed by the harness -dispatcher-exec peel lemma. -/ -theorem simpleStorageNativeContract_dispatcher_eq_singleton_block_inner : - Compiler.SimpleStorageNativeWitness.nativeContract.dispatcher = - .Block [.Block simpleStorageNativeDispatcherInnerStmts] := by - rw [simpleStorageNativeContract_dispatcher_eq_lowered_stmts, - simpleStorageNativeDispatcherStmts_eq_singleton_block] - -/-- Reify the SimpleStorage native witness contract as a record whose -dispatcher is the doubly-blocked inner statement list. - -This packages record-η with the lowered + singleton-block dispatcher -equalities so that the harness peel lemmas (which expect a -`{ dispatcher := .Block body, functions := … }` shape) apply in one rewrite. -/ -theorem simpleStorageNativeContract_eq_record_inner_block : - Compiler.SimpleStorageNativeWitness.nativeContract = - { dispatcher := .Block [.Block simpleStorageNativeDispatcherInnerStmts] - functions := - Compiler.SimpleStorageNativeWitness.nativeContract.functions } := by - have hEta : Compiler.SimpleStorageNativeWitness.nativeContract = - (⟨Compiler.SimpleStorageNativeWitness.nativeContract.dispatcher, - Compiler.SimpleStorageNativeWitness.nativeContract.functions⟩ : - EvmYul.Yul.Ast.YulContract) := rfl - rw [hEta, simpleStorageNativeContract_dispatcher_eq_singleton_block_inner] - -/-- Dispatcher-exec for the SimpleStorage native witness peels TWO outer -`.Block` wrappers (the function-body wrapper installed by the dispatcher exec -plus the singleton-block emitted by `buildSwitch`'s native lowering) into a -direct `EvmYul.Yul.exec` over the inner statement list. - -This collapses the bridge's dispatcher invocation into the same shape the -harness's per-selector body lemmas already speak about, in preparation for -discharging the bridge from those lemmas. -/ -theorem simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec - (peeledFuel : Nat) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (Nat.succ (Nat.succ (Nat.succ peeledFuel))) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = - EvmYul.Yul.exec (Nat.succ peeledFuel) - (.Block simpleStorageNativeDispatcherInnerStmts) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) := by - rw [simpleStorageNativeContract_eq_record_inner_block] - rw [Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_block_dispatcher_eq_exec_block - (Nat.succ peeledFuel) [.Block simpleStorageNativeDispatcherInnerStmts] - Compiler.SimpleStorageNativeWitness.nativeContract.functions - tx storage observableSlots] - rw [Compiler.Proofs.YulGeneration.Backends.Native.exec_singleton_block_eq_exec_block] - -/-- A successful lowering of a singleton `[.block stmts]` reveals exactly the -inner statement-list lowering. This is the structural counterpart of -`lowerStmtsNative_single_block_ok_singleton`: instead of merely existing, the -`inner` argument is the *output* of the inner statement-list lowering. -/ -theorem lowerStmtsNative_block_stmts_eq - (stmts : List Yul.YulStmt) - (inner : List EvmYul.Yul.Ast.Stmt) - (h : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative - [Yul.YulStmt.block stmts] = .ok [.Block inner]) : - ∃ next : Nat, + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames - [Yul.YulStmt.block stmts]) - 0 stmts = .ok (inner, next) := by - unfold Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative at h - dsimp at h - rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons] at h - rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_block] at h - cases hInner : + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames - [Yul.YulStmt.block stmts]) - 0 stmts with - | error err => - rw [hInner] at h - simp only [Bind.bind, Except.bind, reduceCtorEq] at h - | ok pair => - cases pair with - | mk inner' next => - rw [hInner] at h - simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, - Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, - List.append_nil, Except.ok.injEq] at h - injection h with hStmt _ - injection hStmt with hEq - subst hEq - exact ⟨next, rfl⟩ + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 23 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_withSwitchIds_generated_prefix_atFuel_projectResult_eq + fuel' tx.functionSelector reservedNames n0 irContract.functions fn inner + next functions tx state.storage state.events materializedSlots final + nativeYulRaw hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange hPayable hguards hArgs with + ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hFuel hBody' hPreservesMatched rfl with + ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -/-- A `.let_`-headed statement-list lowering peels its head into a singleton -`.Let` statement and threads the unchanged switch counter through the tail. -This generic peel is the per-statement complement of -`lowerStmtsNative_block_stmts_eq`: combined, they reduce a successful native -lowering of a `.let_`-headed block to the lowering of its tail. -/ -theorem lowerStmtsNativeWithSwitchIds_let_head_eq - (reservedNames : List String) (n0 : Nat) - (name : String) (value : Yul.YulExpr) - (rest : List Yul.YulStmt) +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_withSwitchIds_generated_prefix_atFuel + (fuel' : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) - (h : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - reservedNames n0 - (Yul.YulStmt.let_ name value :: rest) = .ok (inner, next)) : - ∃ rest' : List EvmYul.Yul.Ast.Stmt, - inner = EvmYul.Yul.Ast.Stmt.Let [name] - (some - (Compiler.Proofs.YulGeneration.Backends.lowerExprNative value)) - :: rest' ∧ + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - reservedNames n0 rest = .ok (rest', next) := by - rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, - Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_let] - at h - -- Reduce the outer `Except.ok ([letStmt], n0) >>= …` to expose the rest's - -- lowering call directly threaded with `n0`. - simp only [Bind.bind, Except.bind] at h - cases hRest : + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - reservedNames n0 rest with - | error err => - rw [hRest] at h - simp only [reduceCtorEq] at h - | ok pair => - cases pair with - | mk rest' n => - rw [hRest] at h - simp only [Pure.pure, Except.pure, List.singleton_append, - Except.ok.injEq, Prod.mk.injEq] at h - obtain ⟨hList, hNat⟩ := h - subst hNat - exact ⟨rest', hList.symm, rfl⟩ + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 24 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_withSwitchIds_generated_prefix_atFuel_projectResult_eq + fuel' tx.functionSelector reservedNames n0 irContract.functions fn inner + next functions tx state.storage state.events materializedSlots final + nativeYulRaw hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange hNonPayable hguards hArgs with + ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + + suffix.length + 10) (.Block bodyNative) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hFuel hBody' hPreservesMatched rfl with + ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -/-- An `.if_`-headed statement-list lowering peels its head into a singleton -`.If` statement and threads the body's switch-counter advance through to the -tail. This is the per-statement complement of -`lowerStmtsNativeWithSwitchIds_let_head_eq` for the `if_` case: combined with -`lowerStmtsNative_block_stmts_eq`, it lets a successful native lowering of a -block be peeled past an `.if_`-headed source statement. -/ -theorem lowerStmtsNativeWithSwitchIds_if_head_eq - (reservedNames : List String) (n0 : Nat) - (cond : Yul.YulExpr) (body : List Yul.YulStmt) - (rest : List Yul.YulStmt) +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds_atFuel + (fuel' : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) - (h : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - reservedNames n0 - (Yul.YulStmt.if_ cond body :: rest) = .ok (inner, next)) : - ∃ (body' : List EvmYul.Yul.Ast.Stmt) (midN : Nat) - (rest' : List EvmYul.Yul.Ast.Stmt), - inner = EvmYul.Yul.Ast.Stmt.If - (Compiler.Proofs.YulGeneration.Backends.lowerExprNative cond) - body' :: rest' ∧ + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - reservedNames n0 body = .ok (body', midN) ∧ + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - reservedNames midN rest = .ok (rest', next) := by - rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, - Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_if] - at h - cases hBody : - Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - reservedNames n0 body with - | error _ => rw [hBody] at h; simp only [Bind.bind, Except.bind, reduceCtorEq] at h - | ok bodyPair => - obtain ⟨body', midN⟩ := bodyPair - rw [hBody] at h - simp only [Bind.bind, Except.bind, Pure.pure, Except.pure] at h - cases hRest : - Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - reservedNames midN rest with - | error _ => - rw [hRest] at h; simp only [reduceCtorEq] at h - | ok restPair => - obtain ⟨rest', _⟩ := restPair - rw [hRest] at h - simp only [List.singleton_append, Except.ok.injEq, Prod.mk.injEq] at h - obtain ⟨hList, hNat⟩ := h - subst hNat - exact ⟨body', midN, rest', hList.symm, rfl, hRest⟩ + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + (cases'.length + 19 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) body' + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_atFuel_projectResult_eq_preserved + fuel' tx.functionSelector reservedNames n0 irContract.functions fn inner + next functions (YulTransaction.ofIR tx) state.storage state.events + materializedSlots final nativeYulRaw hLower hSelector hFind hNoWrap + hSelectorRangeNative hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro hFuel hBody hPreservesMatched hProject hMatch + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont hFuel hBody' hPreservesMatched rfl with ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -set_option linter.unusedSimpArgs false in -/-- A singleton `.switch`-headed statement-list lowering reduces to a singleton -`.lowerNativeSwitchBlock` over the same source expression. This is the -companion of `lowerStmtsNativeWithSwitchIds_let_head_eq` and `_if_head_eq` -specialized to a single source-level `switch` statement (no tail), which is -exactly the shape produced by the body of `buildSwitch`'s selector-hit `if`. -The case-bodies and default-body lowerings remain abstract because their -shape depends on the concrete contract `funcs` list. -/ -theorem lowerStmtsNativeWithSwitchIds_singleton_switch_eq - (reservedNames : List String) (n0 : Nat) - (expr : Yul.YulExpr) (cases : List (Nat × List Yul.YulStmt)) - (defaultCase : Option (List Yul.YulStmt)) +private theorem nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds_atFuel_forall + (fuel' : Nat) (reservedNames : List String) (n0 : Nat) + (irContract : IRContract) (tx : IRTransaction) + (state : IRState) (observableSlots : List Nat) (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) - (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 - [Yul.YulStmt.switch expr cases defaultCase] = .ok (inner, next)) : - ∃ (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (default' : List EvmYul.Yul.Ast.Stmt), - inner = [Backends.lowerNativeSwitchBlock expr - (Backends.freshNativeSwitchId reservedNames n0) cases' default'] := by - rw [Backends.lowerStmtsNativeWithSwitchIds_cons, - Backends.lowerStmtGroupNativeWithSwitchIds_switch] at h - dsimp only [] at h - cases hCases : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames - (Backends.freshNativeSwitchId reservedNames n0 + 1) cases with - | error _ => - rw [hCases] at h; simp only [Bind.bind, Except.bind, reduceCtorEq] at h - | ok casesPair => - obtain ⟨cases', midN⟩ := casesPair - rw [hCases] at h - simp only [Bind.bind, Except.bind, Pure.pure, Except.pure] at h - cases defaultCase with - | none => - simp only [Backends.lowerStmtsNativeWithSwitchIds_nil, - List.singleton_append, Except.ok.injEq, Prod.mk.injEq] at h - exact ⟨cases', [], h.1.symm⟩ - | some defaultBody => - dsimp only [] at h - cases hDef : Backends.lowerStmtsNativeWithSwitchIds - reservedNames midN defaultBody with - | error _ => - rw [hDef] at h - simp only [Bind.bind, Except.bind, reduceCtorEq] at h - | ok defaultPair => - obtain ⟨default', _⟩ := defaultPair - rw [hDef] at h - simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, - Backends.lowerStmtsNativeWithSwitchIds_nil, - List.singleton_append, Except.ok.injEq, Prod.mk.injEq] at h - exact ⟨cases', default', h.1.symm⟩ + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + (fn : IRFunction) + (hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], next)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + (∀ final nativeYul, + cases'.length + 19 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) body' + (some { dispatcher := .Block [.Block inner], functions := functions })) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul) → + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx state observableSlots + { dispatcher := .Block [.Block inner], functions := functions }) := by + let materializedSlots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + have hSelector : + tx.functionSelector = + tx.functionSelector % Compiler.Constants.selectorModulus := by + exact (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_atFuel_projectResult_eq_preserved_forall + fuel' tx.functionSelector reservedNames n0 irContract.functions fn inner + next functions (YulTransaction.ofIR tx) state.storage state.events + materializedSlots hLower hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro final nativeYul hFuel hBody hPreservesMatched hProject hMatch + let nativeYulRaw := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.ok (final, [])) + have hBody' : + ∀ pre suffix, cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some { dispatcher := .Block [.Block inner], functions := functions }) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + { dispatcher := .Block [.Block inner], functions := functions } + (YulTransaction.ofIR tx) state.storage materializedSlots + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + simpa [materializedSlots] using hBody + rcases hCont final nativeYulRaw hFuel hBody' hPreservesMatched rfl with + ⟨hExec, _hProjectRaw⟩ + refine nativeDispatcherExecMatchesIRPositive_of_project_eq_match + (contract := irContract) (tx := tx) (state := state) + (observableSlots := observableSlots) + (nativeContract := { dispatcher := .Block [.Block inner], functions := functions }) + ?_ hMatch + simp [nativeProjectedDispatcherResultEq, hExec, hProject, materializedSlots] -/-- The head of the SimpleStorage native dispatcher inner-block is the lowered -`let __has_selector := ...` statement. This peels one further layer beyond the -singleton-block extraction (`simpleStorageNativeDispatcherStmts_eq_singleton_block`) -by applying the cons/`_let` lowering equations to the head of `buildSwitch`'s -3-statement block. The remaining tail is left abstract — downstream peels will -expose the second and third statements. -/ -theorem simpleStorageNativeDispatcherInnerStmts_head_let_exists : - ∃ (e : EvmYul.Yul.Ast.Expr) (rest : List EvmYul.Yul.Ast.Stmt), - simpleStorageNativeDispatcherInnerStmts = - EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] (some e) :: rest := by - have hOk := simpleStorageNativeDispatcherStmts_lowering_ok - rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk - obtain ⟨next, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk - -- `buildSwitch ssIRC.functions none none` unfolds (definitionally) to a - -- 3-statement `YulStmt.block` whose head is `let __has_selector := …`, so - -- `hInner` is already a `let_`-headed lowering at the source spine. - obtain ⟨rest', hSplit, _⟩ := - lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner - exact ⟨_, rest', hSplit⟩ - -/-- The first two statements of the SimpleStorage native dispatcher inner-block -are exactly the lowered `let __has_selector := ...` and the lowered selector-miss -guard `if iszero(__has_selector) { revert(0,0) }`. This peels the second -statement of `buildSwitch`'s 3-statement source block by chaining -`lowerStmtsNative_block_stmts_eq`, `lowerStmtsNativeWithSwitchIds_let_head_eq`, -and `lowerStmtsNativeWithSwitchIds_if_head_eq`. -/ -theorem simpleStorageNativeDispatcherInnerStmts_let_if_head_exists : - ∃ (e : EvmYul.Yul.Ast.Expr) (c : EvmYul.Yul.Ast.Expr) - (body : List EvmYul.Yul.Ast.Stmt) (rest : List EvmYul.Yul.Ast.Stmt), - simpleStorageNativeDispatcherInnerStmts = - EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] (some e) :: - EvmYul.Yul.Ast.Stmt.If c body :: - rest := by - have hOk := simpleStorageNativeDispatcherStmts_lowering_ok - rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk - obtain ⟨next, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk - obtain ⟨rest', hLet, hRestLowering⟩ := - lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner - obtain ⟨body', _midN, rest'', hIf, _, _⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering - rw [hIf] at hLet - exact ⟨_, _, body', rest'', hLet⟩ - -/-- The full inner-block of the SimpleStorage native dispatcher has exactly the -expected three-statement shape: the lowered `let __has_selector := …`, the -selector-miss `if iszero(__has_selector) { … }` guard, and the selector-hit -`if __has_selector { switch … }` body. The trailing list is empty because -`buildSwitch` produces a 3-statement source block. -/ -theorem simpleStorageNativeDispatcherInnerStmts_eq_let_if_if : - ∃ (e : EvmYul.Yul.Ast.Expr) (c1 : EvmYul.Yul.Ast.Expr) - (body1 : List EvmYul.Yul.Ast.Stmt) - (c2 : EvmYul.Yul.Ast.Expr) (body2 : List EvmYul.Yul.Ast.Stmt), - simpleStorageNativeDispatcherInnerStmts = - [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] (some e), - EvmYul.Yul.Ast.Stmt.If c1 body1, - EvmYul.Yul.Ast.Stmt.If c2 body2] := by - have hOk := simpleStorageNativeDispatcherStmts_lowering_ok - rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk - obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk - obtain ⟨rest', hLet, hRestLowering⟩ := - lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner - obtain ⟨body1', _, rest'', hIf1, _, hRest1⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering - obtain ⟨body2', _, rest''', hIf2, _, hRest2⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 - rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, - Except.ok.injEq, Prod.mk.injEq] at hRest2 - obtain ⟨hNil, _⟩ := hRest2 - subst hNil - rw [hIf2] at hIf1 - rw [hIf1] at hLet - exact ⟨_, _, body1', _, body2', hLet⟩ +/-- Native contract value produced by helper-free dispatcher-only lowering. -/ +private abbrev nativeContractOfDispatcher + (dispatcher : List EvmYul.Yul.Ast.Stmt) : + EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block dispatcher + functions := + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) } -/-- The lowered RHS expression of the SimpleStorage native dispatcher's -`__has_selector` let. Pinned via `Classical.choose` from the let/if/if shape -existential so it can be referenced by downstream proofs without re-`obtain`-ing -the witness each time. -/ -noncomputable def simpleStorageNativeDispatcher_letValue : - EvmYul.Yul.Ast.Expr := - Classical.choose simpleStorageNativeDispatcherInnerStmts_eq_let_if_if +/-- Native contract value produced by dispatcher lowering when the generated +runtime also includes the native `mappingSlot` helper. -/ +private abbrev nativeContractOfDispatcherWithMapping + (dispatcher : List EvmYul.Yul.Ast.Stmt) : + EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block dispatcher + functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) } -/-- The lowered condition of the SimpleStorage native dispatcher's -selector-miss `if iszero(__has_selector) { … }` guard. -/ -noncomputable def simpleStorageNativeDispatcher_if1Cond : - EvmYul.Yul.Ast.Expr := - Classical.choose - (Classical.choose_spec simpleStorageNativeDispatcherInnerStmts_eq_let_if_if) +/-- Function-level native-fragment body shape from static scalar parameter loads plus +a body-code shape witness. This isolates the shared append/prologue reasoning +needed before the public generated-native wrappers can derive their own +external-body witnesses from compiler output. -/ +private theorem compileFunctionSpec_noFuncDefs_of_static_params_and_body + (fields : List CompilationModel.Field) + (events : List CompilationModel.EventDef) + (errors : List CompilationModel.ErrorDef) + (selector : Nat) (spec : CompilationModel.FunctionSpec) + (irFn : IRFunction) + (hStaticParams : + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams spec.params) + (hBodyNoFuncDefs : + ∀ bodyStmts, + CompilationModel.compileStmtList fields events errors .calldata [] false + (spec.params.map (·.name)) [] spec.body = Except.ok bodyStmts → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + bodyStmts = false) + (hcompile : + CompilationModel.compileFunctionSpec fields events errors [] selector spec = + Except.ok irFn) : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + irFn.body = false := by + rcases Compiler.Proofs.IRGeneration.FunctionShape.compileFunctionSpec_ok_components + fields events errors selector spec irFn hcompile with + ⟨returns, bodyStmts, _hvalidate, _hreturns, hbody, hirFn⟩ + subst irFn + change + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + (CompilationModel.genParamLoads spec.params ++ bodyStmts) = false + simp [ + Compiler.Proofs.YulGeneration.Backends.genParamLoads_static_scalar_noFuncDefs + spec.params hStaticParams, + hBodyNoFuncDefs bodyStmts hbody] -/-- The lowered body of the SimpleStorage native dispatcher's selector-miss -guard (the `revert(0,0)` revert path). -/ -noncomputable def simpleStorageNativeDispatcher_if1Body : - List EvmYul.Yul.Ast.Stmt := - Classical.choose - (Classical.choose_spec - (Classical.choose_spec simpleStorageNativeDispatcherInnerStmts_eq_let_if_if)) +private theorem compileFunctionSpec_noFuncDefs_of_safe_static_params + (fields : List CompilationModel.Field) + (events : List CompilationModel.EventDef) + (errors : List CompilationModel.ErrorDef) + (selector : Nat) (spec : CompilationModel.FunctionSpec) + (irFn : IRFunction) + (hStaticParams : + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams spec.params) + (hSafeBody : + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + fields errors .calldata [] false spec.body) + (hcompile : + CompilationModel.compileFunctionSpec fields events errors [] selector spec = + Except.ok irFn) : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + irFn.body = false := by + rcases Compiler.Proofs.IRGeneration.FunctionShape.compileFunctionSpec_ok_components + fields events errors selector spec irFn hcompile with + ⟨returns, bodyStmts, _hvalidate, _hreturns, hbody, hirFn⟩ + subst irFn + change + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + (CompilationModel.genParamLoads spec.params ++ bodyStmts) = false + simp [ + Compiler.Proofs.YulGeneration.Backends.genParamLoads_static_scalar_noFuncDefs + spec.params hStaticParams, + Compiler.Proofs.YulGeneration.Backends.compileStmtList_always_noFuncDefs + fields events errors .calldata [] false spec.body + (spec.params.map (·.name)) hSafeBody hbody] -/-- The lowered condition of the SimpleStorage native dispatcher's -selector-hit `if __has_selector { switch … }` body. -/ -noncomputable def simpleStorageNativeDispatcher_if2Cond : - EvmYul.Yul.Ast.Expr := - Classical.choose - (Classical.choose_spec - (Classical.choose_spec - (Classical.choose_spec - simpleStorageNativeDispatcherInnerStmts_eq_let_if_if))) +/-- Convert the new source-level safe-body closure theorem into the low-level +`BridgedStmts fn.body` witness still consumed by the EVMYulLean runtime +retargeting theorem. This is the key local bridge from compiler-produced +`FunctionSpec` bodies to emitted IR function bodies: static scalar parameter +loads are bridged by the prologue theorem, and the compiled source body is +bridged by `compileStmtList_always_bridged`. -/ +private theorem compileFunctionSpec_bridged_of_safe_static_params + (fields : List CompilationModel.Field) + (events : List CompilationModel.EventDef) + (errors : List CompilationModel.ErrorDef) + (selector : Nat) (spec : CompilationModel.FunctionSpec) + (irFn : IRFunction) + (hStaticParams : + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams spec.params) + (hSafeBody : + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + fields errors .calldata [] false spec.body) + (hcompile : + CompilationModel.compileFunctionSpec fields events errors [] selector spec = + Except.ok irFn) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts irFn.body := by + rcases Compiler.Proofs.IRGeneration.FunctionShape.compileFunctionSpec_ok_components + fields events errors selector spec irFn hcompile with + ⟨returns, bodyStmts, _hvalidate, _hreturns, hbody, hirFn⟩ + subst irFn + change + Compiler.Proofs.YulGeneration.Backends.BridgedStmts + (CompilationModel.genParamLoads spec.params ++ bodyStmts) + exact Compiler.Proofs.YulGeneration.Backends.BridgedStmts_append + (Compiler.Proofs.YulGeneration.Backends.genParamLoads_static_scalar_bridged + spec.params hStaticParams) + (Compiler.Proofs.YulGeneration.Backends.compileStmtList_always_bridged + fields events errors .calldata [] false spec.body + (spec.params.map (·.name)) hSafeBody hbody) -/-- The lowered body of the SimpleStorage native dispatcher's selector-hit -`if __has_selector { switch … }` body — i.e., the singleton list containing -the lowered `switch` over the three generated cases. -/ -noncomputable def simpleStorageNativeDispatcher_if2Body : - List EvmYul.Yul.Ast.Stmt := - Classical.choose - (Classical.choose_spec - (Classical.choose_spec - (Classical.choose_spec - (Classical.choose_spec - simpleStorageNativeDispatcherInnerStmts_eq_let_if_if)))) +/-- Lift the one-function bridge closure theorem across the compiled external +function table. This keeps the public EndToEnd theorem from exposing raw +`BridgedStmts fn.body` obligations when callers already have source-level +safe-body/static-param witnesses for every selector-dispatched function. -/ +private theorem compiledExternalFunctions_bridged_of_safe_static + (fields : List CompilationModel.Field) + (events : List CompilationModel.EventDef) + (errors : List CompilationModel.ErrorDef) : + ∀ {entries : List (CompilationModel.FunctionSpec × Nat)} + {irFns : List IRFunction}, + List.Forall₂ + (fun entry irFn => + CompilationModel.compileFunctionSpec fields events errors + [] entry.2 entry.1 = Except.ok irFn) + entries irFns → + (∀ entry, entry ∈ entries → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams + entry.1.params) → + (∀ entry, entry ∈ entries → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + fields errors .calldata [] false entry.1.body) → + ∀ irFn, irFn ∈ irFns → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts irFn.body := by + intro entries irFns hcompiled hStatic hSafe + induction hcompiled with + | nil => + intro irFn hmem + cases hmem + | @cons entry irFn entries irFns hhead htail ih => + intro target hmem + simp only [List.mem_cons] at hmem + rcases hmem with rfl | hmemTail + · exact compileFunctionSpec_bridged_of_safe_static_params + fields events errors entry.2 entry.1 target + (hStatic entry (by simp)) + (hSafe entry (by simp)) + hhead + · exact ih + (fun next hnext => hStatic next (by simp [hnext])) + (fun next hnext => hSafe next (by simp [hnext])) + target hmemTail -/-- Closed-form decomposition of the SimpleStorage native dispatcher inner -statement list using the named witness defs. Eliminates the existential -boilerplate from the `_eq_let_if_if` lemma so future selector-case proofs can -rewrite the dispatcher inner-stmts to a literal 3-element list. -/ -theorem simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if : - simpleStorageNativeDispatcherInnerStmts = - [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] - (some simpleStorageNativeDispatcher_letValue), - EvmYul.Yul.Ast.Stmt.If - simpleStorageNativeDispatcher_if1Cond - simpleStorageNativeDispatcher_if1Body, - EvmYul.Yul.Ast.Stmt.If - simpleStorageNativeDispatcher_if2Cond - simpleStorageNativeDispatcher_if2Body] := - Classical.choose_spec - (Classical.choose_spec - (Classical.choose_spec - (Classical.choose_spec - (Classical.choose_spec - simpleStorageNativeDispatcherInnerStmts_eq_let_if_if)))) +/-- Lift function-level native-fragment body shape across the compiled external +function table. This is the no-`funcDef` analogue of +`compiledExternalFunctions_bridged_of_safe_static`, staged separately because +the body-shape source predicate is still being proved fragment by fragment. -/ +private theorem compiledExternalFunctions_noFuncDefs_of_static_params_and_body + (fields : List CompilationModel.Field) + (events : List CompilationModel.EventDef) + (errors : List CompilationModel.ErrorDef) : + ∀ {entries : List (CompilationModel.FunctionSpec × Nat)} + {irFns : List IRFunction}, + List.Forall₂ + (fun entry irFn => + CompilationModel.compileFunctionSpec fields events errors + [] entry.2 entry.1 = Except.ok irFn) + entries irFns → + (∀ entry, entry ∈ entries → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams + entry.1.params) → + (∀ entry, entry ∈ entries → + ∀ bodyStmts, + CompilationModel.compileStmtList fields events errors .calldata [] false + (entry.1.params.map (·.name)) [] entry.1.body = + Except.ok bodyStmts → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + bodyStmts = false) → + ∀ irFn, irFn ∈ irFns → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + irFn.body = false := by + intro entries irFns hcompiled hStatic hBody + induction hcompiled with + | nil => + intro irFn hmem + cases hmem + | @cons entry irFn entries irFns hhead htail ih => + intro target hmem + simp only [List.mem_cons] at hmem + rcases hmem with rfl | hmemTail + · exact compileFunctionSpec_noFuncDefs_of_static_params_and_body + fields events errors entry.2 entry.1 target + (hStatic entry (by simp)) + (hBody entry (by simp)) + hhead + · exact ih + (fun next hnext => hStatic next (by simp [hnext])) + (fun next hnext => hBody next (by simp [hnext])) + target hmemTail -/-- Composed structural form of the SimpleStorage native dispatcher exec: -the doubly-blocked dispatcher is exposed at the concrete inner three-statement -spine using the pinned named witnesses. This combines -`simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec` with -`simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if`, replacing the -existential let/if/if shape with a concrete equation in named witnesses. -/ -theorem simpleStorageNativeContract_dispatcherExec_eq_named_let_if_if_block_exec - (peeledFuel : Nat) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (Nat.succ (Nat.succ (Nat.succ peeledFuel))) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = - EvmYul.Yul.exec (Nat.succ peeledFuel) - (.Block - [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] - (some simpleStorageNativeDispatcher_letValue), - EvmYul.Yul.Ast.Stmt.If - simpleStorageNativeDispatcher_if1Cond - simpleStorageNativeDispatcher_if1Body, - EvmYul.Yul.Ast.Stmt.If - simpleStorageNativeDispatcher_if2Cond - simpleStorageNativeDispatcher_if2Body]) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) := by - rw [simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec, - simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if] +private theorem compiledExternalFunctions_noFuncDefs_of_safe_static + (fields : List CompilationModel.Field) + (events : List CompilationModel.EventDef) + (errors : List CompilationModel.ErrorDef) : + ∀ {entries : List (CompilationModel.FunctionSpec × Nat)} + {irFns : List IRFunction}, + List.Forall₂ + (fun entry irFn => + CompilationModel.compileFunctionSpec fields events errors + [] entry.2 entry.1 = Except.ok irFn) + entries irFns → + (∀ entry, entry ∈ entries → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams + entry.1.params) → + (∀ entry, entry ∈ entries → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + fields errors .calldata [] false entry.1.body) → + ∀ irFn, irFn ∈ irFns → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + irFn.body = false := by + intro entries irFns hcompiled hStatic hSafe + induction hcompiled with + | nil => + intro irFn hmem + cases hmem + | @cons entry irFn entries irFns hhead htail ih => + intro target hmem + simp only [List.mem_cons] at hmem + rcases hmem with rfl | hmemTail + · exact compileFunctionSpec_noFuncDefs_of_safe_static_params + fields events errors entry.2 entry.1 target + (hStatic entry (by simp)) + (hSafe entry (by simp)) + hhead + · exact ih + (fun next hnext => hStatic next (by simp [hnext])) + (fun next hnext => hSafe next (by simp [hnext])) + target hmemTail -/-- Concrete head exposure of the SimpleStorage native dispatcher inner-block: -its first statement is the lowered `let __has_selector := iszero(lt(calldatasize(), 4))` -that `buildSwitch` emits, with the source-Yul RHS pinned explicitly. This is -the same peel as `simpleStorageNativeDispatcherInnerStmts_head_let_exists` but -exposes the *concrete* lowered RHS (not just an abstract Lean witness), so the -`Classical.choose`-pinned `simpleStorageNativeDispatcher_letValue` can be -equated to it via head injection. -/ -theorem simpleStorageNativeDispatcherInnerStmts_concrete_let_head : - ∃ rest : List EvmYul.Yul.Ast.Stmt, - simpleStorageNativeDispatcherInnerStmts = - EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] - (some - (Compiler.Proofs.YulGeneration.Backends.lowerExprNative - (Yul.YulExpr.call "iszero" - [Yul.YulExpr.call "lt" - [Yul.YulExpr.call "calldatasize" [], - Yul.YulExpr.lit 4]]))) :: rest := by - have hOk := simpleStorageNativeDispatcherStmts_lowering_ok - rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk - obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk - obtain ⟨rest', hSplit, _⟩ := - lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner - exact ⟨rest', hSplit⟩ +/-- Generic native Layer 3 identity seam on the direct native-vs-IR target. +Kept private so the public theorem surface is the generated-dispatcher family +that exposes concrete native execution obligations. -/ +private theorem layer3_contract_preserves_semantics_native + (fuel : Nat) (contract : IRContract) (tx : IRTransaction) + (initialState : IRState) (observableSlots : List Nat) + (hNativeBridge : nativeIRRuntimeMatchesIR fuel contract tx initialState observableSlots) : + nativeResultsMatchOn observableSlots (interpretIR contract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + fuel contract tx initialState observableSlots) := + hNativeBridge -/-- Concrete-form equation for the SimpleStorage native dispatcher's full inner -3-statement block, pinning *all three* source-Yul expressions (the let RHS, the -selector-miss `iszero(__has_selector)` guard, and the selector-hit -`__has_selector` guard) to the literal Yul expressions emitted by -`buildSwitch`. Only the two `If` bodies remain existential, since they depend -on the lowering of the inner switch over the generated cases. This is the -companion of `simpleStorageNativeDispatcherInnerStmts_eq_let_if_if` with -abstract Yul witnesses replaced by concrete syntax. -/ -theorem simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_if : - ∃ (body1 body2 : List EvmYul.Yul.Ast.Stmt), - simpleStorageNativeDispatcherInnerStmts = - [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] - (some - (Compiler.Proofs.YulGeneration.Backends.lowerExprNative - (Yul.YulExpr.call "iszero" - [Yul.YulExpr.call "lt" - [Yul.YulExpr.call "calldatasize" [], - Yul.YulExpr.lit 4]]))), - EvmYul.Yul.Ast.Stmt.If - (Compiler.Proofs.YulGeneration.Backends.lowerExprNative - (Yul.YulExpr.call "iszero" - [Yul.YulExpr.ident "__has_selector"])) - body1, - EvmYul.Yul.Ast.Stmt.If - (Compiler.Proofs.YulGeneration.Backends.lowerExprNative - (Yul.YulExpr.ident "__has_selector")) - body2] := by - have hOk := simpleStorageNativeDispatcherStmts_lowering_ok - rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk - obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk - obtain ⟨rest', hLet, hRestLowering⟩ := - lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner - obtain ⟨body1', _, rest'', hIf1, _, hRest1⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering - obtain ⟨body2', _, rest''', hIf2, _, hRest2⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 - rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, - Except.ok.injEq, Prod.mk.injEq] at hRest2 - obtain ⟨hNil, _⟩ := hRest2 - subst hNil - rw [hIf2] at hIf1 - rw [hIf1] at hLet - exact ⟨body1', body2', hLet⟩ +/-- Native Layer 3 generated-shape variant at raw lowered-dispatcher exec on +the direct native-vs-IR target. -/ +private theorem layer3_contract_preserves_semantics_native_of_generated_dispatcherExec_positive_match + (fuel' : Nat) (contract : IRContract) (tx : IRTransaction) + (initialState : IRState) (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (hPrefixUnique : Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique + ((if contract.usesMapping then [Compiler.mappingSlotFuncAt 0] else []) ++ + contract.internalFunctions) = true) + (hInternals : ∀ stmt, stmt ∈ contract.internalFunctions → + ∃ name params rets body, stmt = Yul.YulStmt.funcDef name params rets body) + (hExternalBodies : ∀ fn, fn ∈ contract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef fn.body = false) + (hInternalBodies : ∀ name params rets body, + Yul.YulStmt.funcDef name params rets body ∈ contract.internalFunctions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef body = false) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul contract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' contract tx initialState + observableSlots nativeContract) : + nativeResultsMatchOn observableSlots (interpretIR contract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') contract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_positive_match + hPrefixUnique hInternals hExternalBodies hInternalBodies hNoFallback + hNoReceive hLower hEnv hNativeDispatcherExec -/-- Strengthened concrete-form equation for the SimpleStorage native dispatcher -inner-block: same as `simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_if` -except the body of the second (selector-hit) `If` is pinned to a singleton -`lowerNativeSwitchBlock` over the source-Yul `selectorExpr` scrutinee. The -selector cases and default body remain existential because they depend on the -contract's `functions` list. This is the next dispatcher peel beyond the -let/if/if shape and is the foundation for replacing the Classical.choose-pinned -`simpleStorageNativeDispatcher_if2Body` with a concrete switch block. -/ -theorem simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton : - ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (default' : List EvmYul.Yul.Ast.Stmt), - simpleStorageNativeDispatcherInnerStmts = - [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] - (some (Backends.lowerExprNative - (Yul.YulExpr.call "iszero" - [Yul.YulExpr.call "lt" - [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit 4]]))), - EvmYul.Yul.Ast.Stmt.If - (Backends.lowerExprNative - (Yul.YulExpr.call "iszero" [Yul.YulExpr.ident "__has_selector"])) - body1, - EvmYul.Yul.Ast.Stmt.If - (Backends.lowerExprNative (Yul.YulExpr.ident "__has_selector")) - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' default']] := by - have hOk := simpleStorageNativeDispatcherStmts_lowering_ok - rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk - obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk - obtain ⟨_, hLet, hRestLowering⟩ := - lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner - obtain ⟨body1', _, _, hIf1, _, hRest1⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering - obtain ⟨_, _, _, hIf2, hBody2, hRest2⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 - rw [Backends.lowerStmtsNativeWithSwitchIds_nil, - Except.ok.injEq, Prod.mk.injEq] at hRest2 - obtain ⟨hNil, _⟩ := hRest2 - subst hNil - obtain ⟨cases', default', hBody2Eq⟩ := - lowerStmtsNativeWithSwitchIds_singleton_switch_eq _ _ _ _ _ _ _ hBody2 - rw [hBody2Eq] at hIf2; rw [hIf2] at hIf1; rw [hIf1] at hLet - exact ⟨body1', _, cases', default', hLet⟩ +/-! ## Layers 2+3 Composition -/ -/-- WithSwitchIds-form companion of `lowerStmtsNative_revert_zero_zero`: at any -`reservedNames`/`nextSwitchId` pair, the singleton list `[expr (revert(0,0))]` -emitted by `defaultDispatchCase none none` lowers to -`[nativeRevertZeroZeroStmt]` while leaving the switch counter unchanged. The -dispatcher peel uses `lowerStmtsNativeWithSwitchIds` directly (via -`_block_stmts_eq` / `_let_head_eq` / `_if_head_eq`), so the wrapper-level -`lowerStmtsNative_revert_zero_zero` lemma alone is insufficient when pinning -the selector-miss `If` body. -/ -theorem lowerStmtsNativeWithSwitchIds_revert_zero_zero - (reservedNames : List String) (n : Nat) : - Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds - reservedNames n - [Yul.YulStmt.expr (Yul.YulExpr.call "revert" - [Yul.YulExpr.lit 0, Yul.YulExpr.lit 0])] = - .ok ([Backends.Native.nativeRevertZeroZeroStmt], n) := by - simp [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds, - Backends.Native.nativeRevertZeroZeroStmt, - Compiler.Proofs.YulGeneration.Backends.lowerExprNative, - Compiler.Proofs.YulGeneration.Backends.lookupRuntimePrimOp] - rfl +/-- Supported native identity seam on the direct native-vs-IR target. Kept +private so public supported-contract theorems use the generated-dispatcher +wrappers below. -/ +private theorem layers2_3_ir_matches_native_evmYulLean + (fuel : Nat) + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) + (initialState : IRState) (observableSlots : List Nat) + (_hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hNativeBridge : nativeIRRuntimeMatchesIR fuel irContract tx + initialState observableSlots) : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + fuel irContract tx initialState observableSlots) := + hNativeBridge -set_option linter.unusedSimpArgs false in -/-- Strengthened companion of `lowerStmtsNativeWithSwitchIds_singleton_switch_eq`: -when the source-level switch's `defaultCase` is fixed to the -`defaultDispatchCase none none` body — namely the singleton list -`[expr (revert(0,0))]` — the lowered default body is concretely -`[nativeRevertZeroZeroStmt]`. The lowered case bodies remain existential -(they depend on the contract `funcs` list). This pins the previously-existential -`default'` produced by `_singleton_switch_eq`, unblocking downstream proofs -that need to plug the lowered-switch exec into a concrete default-revert -endpoint. -/ -theorem lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq - (reservedNames : List String) (n0 : Nat) - (expr : Yul.YulExpr) (cases : List (Nat × List Yul.YulStmt)) - (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) - (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 - [Yul.YulStmt.switch expr cases - (some [Yul.YulStmt.expr (Yul.YulExpr.call "revert" - [Yul.YulExpr.lit 0, Yul.YulExpr.lit 0])])] = .ok (inner, next)) : - ∃ (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), - inner = [Backends.lowerNativeSwitchBlock expr - (Backends.freshNativeSwitchId reservedNames n0) cases' - [Backends.Native.nativeRevertZeroZeroStmt]] := by - rw [Backends.lowerStmtsNativeWithSwitchIds_cons, - Backends.lowerStmtGroupNativeWithSwitchIds_switch] at h - dsimp only [] at h - cases hCases : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames - (Backends.freshNativeSwitchId reservedNames n0 + 1) cases with - | error _ => - rw [hCases] at h; simp only [Bind.bind, Except.bind, reduceCtorEq] at h - | ok casesPair => - obtain ⟨cases', midN⟩ := casesPair - rw [hCases] at h - simp only [Bind.bind, Except.bind, Pure.pure, Except.pure] at h - rw [lowerStmtsNativeWithSwitchIds_revert_zero_zero] at h - simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, - Backends.lowerStmtsNativeWithSwitchIds_nil, - List.singleton_append, Except.ok.injEq, Prod.mk.injEq] at h - exact ⟨cases', h.1.symm⟩ +/-- Supported compiler output has a unique generated-runtime helper prefix. -set_option linter.unusedSimpArgs false in -/-- Source-lowered companion of `_singleton_switch_revert_default_eq`: also -exposes the `lowerSwitchCasesNativeWithSwitchIds` equation linking the source -case list to the lowered `cases'`. Downstream selector-miss reductions chain -this with `lowerSwitchCasesNativeWithSwitchIds_tags_eq` / -`lowerSwitchCasesNativeWithSwitchIds_find?_none` to lift source-level selector -facts through the lowering. -/ -theorem lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered - (reservedNames : List String) (n0 : Nat) - (expr : Yul.YulExpr) (cases : List (Nat × List Yul.YulStmt)) - (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) - (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 - [Yul.YulStmt.switch expr cases - (some [Yul.YulStmt.expr (Yul.YulExpr.call "revert" - [Yul.YulExpr.lit 0, Yul.YulExpr.lit 0])])] = .ok (inner, next)) : - ∃ (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), - inner = [Backends.lowerNativeSwitchBlock expr - (Backends.freshNativeSwitchId reservedNames n0) cases' - [Backends.Native.nativeRevertZeroZeroStmt]] ∧ - Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames - (Backends.freshNativeSwitchId reservedNames n0 + 1) cases = - .ok (cases', midN) := by - rw [Backends.lowerStmtsNativeWithSwitchIds_cons, - Backends.lowerStmtGroupNativeWithSwitchIds_switch] at h - dsimp only [] at h - cases hCases : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames - (Backends.freshNativeSwitchId reservedNames n0 + 1) cases with - | error _ => - rw [hCases] at h; simp only [Bind.bind, Except.bind, reduceCtorEq] at h - | ok casesPair => - obtain ⟨cases', midN⟩ := casesPair - rw [hCases] at h - simp only [Bind.bind, Except.bind, Pure.pure, Except.pure] at h - rw [lowerStmtsNativeWithSwitchIds_revert_zero_zero] at h - simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, - Backends.lowerStmtsNativeWithSwitchIds_nil, - List.singleton_append, Except.ok.injEq, Prod.mk.injEq] at h - exact ⟨cases', midN, h.1.symm, rfl⟩ +`SupportedSpec` rules out emitted internal helper definitions, leaving only the +optional mapping-slot helper in the generated runtime prefix. -/ +private theorem isStaticScalarParamType_of_supportedExternalParamType + {ty : CompilationModel.ParamType} + (hSupported : SupportedExternalParamType ty) : + Compiler.Proofs.YulGeneration.Backends.IsStaticScalarParamType ty := by + cases ty <;> simp [SupportedExternalParamType] at hSupported + all_goals + exact Compiler.Proofs.YulGeneration.Backends.IsStaticScalarParamType.scalar + (by trivial) -/-- Strengthened companion of `simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton`: -the lowered default body of the inner switch is pinned to the concrete -`[nativeRevertZeroZeroStmt]` singleton. The lowered case bodies (and the -selector-miss `If` body `body1`) remain existential as before. Combines the -existing concrete decomposition with the new -`lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq`, exploiting -the definitional fact that `simpleStorageIRContract` has both `fallback` and -`receive` set to `none`, so the switch's source-level `defaultCase` is -`defaultDispatchCase none none = [revert(0,0)]`. -/ -theorem simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default : - ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), - simpleStorageNativeDispatcherInnerStmts = - [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] - (some (Backends.lowerExprNative - (Yul.YulExpr.call "iszero" - [Yul.YulExpr.call "lt" - [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit 4]]))), - EvmYul.Yul.Ast.Stmt.If - (Backends.lowerExprNative - (Yul.YulExpr.call "iszero" [Yul.YulExpr.ident "__has_selector"])) - body1, - EvmYul.Yul.Ast.Stmt.If - (Backends.lowerExprNative (Yul.YulExpr.ident "__has_selector")) - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' - [Backends.Native.nativeRevertZeroZeroStmt]]] := by - have hOk := simpleStorageNativeDispatcherStmts_lowering_ok - rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk - obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk - obtain ⟨_, hLet, hRestLowering⟩ := - lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner - obtain ⟨body1', _, _, hIf1, _, hRest1⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering - obtain ⟨_, _, _, hIf2, hBody2, hRest2⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 - rw [Backends.lowerStmtsNativeWithSwitchIds_nil, - Except.ok.injEq, Prod.mk.injEq] at hRest2 - obtain ⟨hNil, _⟩ := hRest2 - subst hNil - obtain ⟨cases', hBody2Eq⟩ := - lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq - _ _ _ _ _ _ hBody2 - rw [hBody2Eq] at hIf2; rw [hIf2] at hIf1; rw [hIf1] at hLet - exact ⟨body1', _, cases', hLet⟩ +private theorem allStaticScalarParams_of_supportedExternalParams + {params : List CompilationModel.Param} + (hSupported : + ∀ param ∈ params, SupportedExternalParamType param.ty) : + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams params := by + intro param hmem + exact isStaticScalarParamType_of_supportedExternalParamType + (hSupported param hmem) -/-- The source-level switch cases that `buildSwitch` emits for SimpleStorage -(one entry per source IR function, keyed by selector). Used by the -`_sourceLowered` companion below as the explicit input to -`lowerSwitchCasesNativeWithSwitchIds`, anchoring the switch lowering to the -concrete source-level selector list. -/ -abbrev simpleStorageBuildSwitchSourceCases : List (Nat × List Yul.YulStmt) := - simpleStorageIRContract.functions.map (fun fn => - (fn.selector, - Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" - ([Compiler.CodegenCommon.calldatasizeGuard fn.params.length] ++ fn.body))) +private theorem generatedRuntimeStaticScalarParams_of_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams + entry.1.params := by + intro entry hentry + have hfn : entry.1 ∈ selectorDispatchedFunctions spec := by + simpa [SourceSemantics.selectorFunctionPairs] using + (List.of_mem_zip hentry).1 + exact allStaticScalarParams_of_supportedExternalParams + (hSupported.selectorFunctionParamsSupported hfn) -/-- Source-lowered companion of `_eq_concrete_let_if_switchSingleton_revert_default`: -additionally exposes the lowering equation for the buildSwitch-emitted source -case list `simpleStorageBuildSwitchSourceCases` into the lowered `cases'`. -Bridge lemma for the selector-miss closed-form: chained with -`lowerSwitchCasesNativeWithSwitchIds_tags_eq` it converts source-level -selector facts into lowered-level `find?` results. -/ -theorem simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default_sourceLowered : - ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (reservedNames : List String) (n0 : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), - simpleStorageNativeDispatcherInnerStmts = - [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] - (some (Backends.lowerExprNative (Yul.YulExpr.call "iszero" - [Yul.YulExpr.call "lt" - [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit 4]]))), - EvmYul.Yul.Ast.Stmt.If - (Backends.lowerExprNative - (Yul.YulExpr.call "iszero" [Yul.YulExpr.ident "__has_selector"])) body1, - EvmYul.Yul.Ast.Stmt.If - (Backends.lowerExprNative (Yul.YulExpr.ident "__has_selector")) - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - (Backends.freshNativeSwitchId reservedNames n0) cases' - [Backends.Native.nativeRevertZeroZeroStmt]]] ∧ - Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames - (Backends.freshNativeSwitchId reservedNames n0 + 1) - simpleStorageBuildSwitchSourceCases = .ok (cases', midN) := by - have hOk := simpleStorageNativeDispatcherStmts_lowering_ok - rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk - obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk - obtain ⟨_, hLet, hRestLowering⟩ := - lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner - obtain ⟨body1', _, _, hIf1, _, hRest1⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering - obtain ⟨_, _, _, hIf2, hBody2, hRest2⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 - rw [Backends.lowerStmtsNativeWithSwitchIds_nil, - Except.ok.injEq, Prod.mk.injEq] at hRest2 - obtain ⟨hNil, _⟩ := hRest2 - subst hNil - obtain ⟨cases', midN, hBody2Eq, hLowerCases⟩ := - lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered - _ _ _ _ _ _ hBody2 - rw [hBody2Eq] at hIf2; rw [hIf2] at hIf1; rw [hIf1] at hLet - exact ⟨body1', _, _, cases', midN, hLet, hLowerCases⟩ +private theorem generatedRuntimeStaticScalarParams_of_supported_except_mapping_writes + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpecExceptMappingWrites spec selectors) : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams + entry.1.params := by + intro entry hentry + have hfn : entry.1 ∈ selectorDispatchedFunctions spec := by + simpa [SourceSemantics.selectorFunctionPairs] using + (List.of_mem_zip hentry).1 + exact allStaticScalarParams_of_supportedExternalParams + (hSupported.selectorFunctionParamsSupported hfn) -/-- The `Classical.choose`-pinned let RHS of the SimpleStorage native dispatcher -equals the lowered `iszero(lt(calldatasize(), 4))` Yul expression that -`buildSwitch` emits. Combining the named-form decomposition -(`simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if`) with the -concrete-head exposure -(`simpleStorageNativeDispatcherInnerStmts_concrete_let_head`) and head -injection eliminates the structural existential between the named witness and -the concrete source expression, letting downstream proofs evaluate the let -RHS directly via the existing harness lemmas. -/ -theorem simpleStorageNativeDispatcher_letValue_eq : - simpleStorageNativeDispatcher_letValue = - Compiler.Proofs.YulGeneration.Backends.lowerExprNative - (Yul.YulExpr.call "iszero" - [Yul.YulExpr.call "lt" - [Yul.YulExpr.call "calldatasize" [], - Yul.YulExpr.lit 4]]) := by - obtain ⟨_, hConcrete⟩ := - simpleStorageNativeDispatcherInnerStmts_concrete_let_head - have hCombo := - simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete - simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.Let.injEq, Option.some.injEq, - true_and] at hCombo - exact hCombo.1 +private theorem exists_left_of_forall₂_mem_right + {α β : Type} {R : α → β → Prop} {xs : List α} {ys : List β} + (hrel : List.Forall₂ R xs ys) : + ∀ {y}, y ∈ ys → ∃ x, x ∈ xs ∧ R x y := by + intro y hy + induction hrel with + | nil => + simp at hy + | @cons headX headY tailX tailY hhead htail ih => + simp only [List.mem_cons] at hy + rcases hy with rfl | hyTail + · exact ⟨headX, by simp, hhead⟩ + · rcases ih hyTail with ⟨x, hx, hRx⟩ + exact ⟨x, by simp [hx], hRx⟩ -/-- The `Classical.choose`-pinned selector-miss guard condition of the -SimpleStorage native dispatcher equals the lowered `iszero(__has_selector)` -Yul expression that `buildSwitch` emits. Derived by head injection from the -concrete-form full equation and the named-form decomposition. -/ -theorem simpleStorageNativeDispatcher_if1Cond_eq : - simpleStorageNativeDispatcher_if1Cond = - Compiler.Proofs.YulGeneration.Backends.lowerExprNative - (Yul.YulExpr.call "iszero" - [Yul.YulExpr.ident "__has_selector"]) := by - obtain ⟨_, _, hConcrete⟩ := - simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_if - have hCombo := - simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete - simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo - exact hCombo.2.1.1 +private theorem snd_mem_of_mem_zip + {α β : Type} {xs : List α} {ys : List β} {x : α} {y : β} + (hmem : (x, y) ∈ xs.zip ys) : + y ∈ ys := by + induction xs generalizing ys with + | nil => + simp at hmem + | cons head tail ih => + cases ys with + | nil => + simp at hmem + | cons yHead yTail => + simp only [List.zip_cons_cons, List.mem_cons] at hmem + rcases hmem with hhead | htail + · cases hhead + simp + · exact List.mem_cons_of_mem yHead (ih htail) -/-- The `Classical.choose`-pinned selector-hit guard condition of the -SimpleStorage native dispatcher equals the lowered `__has_selector` ident -expression that `buildSwitch` emits. Derived by head injection from the -concrete-form full equation and the named-form decomposition. -/ -theorem simpleStorageNativeDispatcher_if2Cond_eq : - simpleStorageNativeDispatcher_if2Cond = - Compiler.Proofs.YulGeneration.Backends.lowerExprNative - (Yul.YulExpr.ident "__has_selector") := by - obtain ⟨_, _, hConcrete⟩ := - simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_if - have hCombo := - simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete - simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo - exact hCombo.2.2.1.1 +private theorem selectorModulus_lt_uint256 : + Compiler.Constants.selectorModulus < EvmYul.UInt256.size := by + norm_num [Compiler.Constants.selectorModulus, EvmYul.UInt256.size] -/-- The `Classical.choose`-pinned selector-hit `If` body of the SimpleStorage -native dispatcher equals a singleton `lowerNativeSwitchBlock` over the -source-Yul `selectorExpr` (i.e., `shr(selectorShift, calldataload(0))`). The -switch-id, lowered case bodies, and lowered default body remain existential -because they depend on the concrete contract `functions` list — but their -existence as a closed-form switch block is enough to drive the next dispatcher -peel into selector-case dispatch. Derived by head injection from the -strengthened concrete-form `_eq_concrete_let_if_switchSingleton` and the -named-form decomposition. -/ -theorem simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_exists : - ∃ (switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (default' : List EvmYul.Yul.Ast.Stmt), - simpleStorageNativeDispatcher_if2Body = - [Compiler.Proofs.YulGeneration.Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' default'] := by - obtain ⟨_, switchId, cases', default', hConcrete⟩ := - simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton - have hCombo := - simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete - simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo - exact ⟨switchId, cases', default', hCombo.2.2.1.2⟩ +theorem generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := by + intro fn hmem + have hCompiled := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions + spec selectors hSupported irContract hCompile + rcases exists_left_of_forall₂_mem_right hCompiled hmem with + ⟨entry, hentryMem, hCompileFn⟩ + have hSelectorEq : + fn.selector = entry.2 := + Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_selector + spec.fields spec.events spec.errors entry.2 entry.1 fn hCompileFn + have hSelectorMem : entry.2 ∈ selectors := by + simpa [SourceSemantics.selectorFunctionPairs] using + (snd_mem_of_mem_zip hentryMem) + rw [hSelectorEq] + exact Nat.lt_trans (hSelectorsRange entry.2 hSelectorMem) + selectorModulus_lt_uint256 -/-- Strengthened companion of `simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_exists`: -the lowered default body of the dispatcher's selector-hit switch is pinned to -`[nativeRevertZeroZeroStmt]`. Derived by head injection from the strengthened -concrete-form `_eq_concrete_let_if_switchSingleton_revert_default` and the -named-form decomposition. -/ -theorem simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_exists : - ∃ (switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), - simpleStorageNativeDispatcher_if2Body = - [Compiler.Proofs.YulGeneration.Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' - [Backends.Native.nativeRevertZeroZeroStmt]] := by - obtain ⟨_, switchId, cases', hConcrete⟩ := - simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default - have hCombo := - simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete - simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo - exact ⟨switchId, cases', hCombo.2.2.1.2⟩ +theorem generatedRuntimeFunctionSelectorsSelectorRange_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) : + ∀ fn, fn ∈ irContract.functions → + fn.selector < Compiler.Constants.selectorModulus := by + intro fn hmem + have hCompiled := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions + spec selectors hSupported irContract hCompile + rcases exists_left_of_forall₂_mem_right hCompiled hmem with + ⟨entry, hentryMem, hCompileFn⟩ + have hSelectorEq : + fn.selector = entry.2 := + Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_selector + spec.fields spec.events spec.errors entry.2 entry.1 fn hCompileFn + have hSelectorMem : entry.2 ∈ selectors := by + simpa [SourceSemantics.selectorFunctionPairs] using + (snd_mem_of_mem_zip hentryMem) + rw [hSelectorEq] + exact hSelectorsRange entry.2 hSelectorMem -/-- Source-lowered companion of `_if2Body_eq_lowerSwitchBlock_revert_default_exists`: -the `if2Body` equality additionally exposes `switchId = -freshNativeSwitchId reservedNames n0` and the source-cases lowering equation -linking `simpleStorageBuildSwitchSourceCases` to the lowered `cases'`. This is -the form the dispatcher selector-miss closed-form consumes — chaining it with -`lowerSwitchCasesNativeWithSwitchIds_tags_eq` lifts source-level selector -facts through the lowering. -/ -theorem simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_sourceLowered : - ∃ (reservedNames : List String) (n0 : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), - simpleStorageNativeDispatcher_if2Body = - [Compiler.Proofs.YulGeneration.Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - (Backends.freshNativeSwitchId reservedNames n0) cases' - [Backends.Native.nativeRevertZeroZeroStmt]] ∧ - Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames - (Backends.freshNativeSwitchId reservedNames n0 + 1) - simpleStorageBuildSwitchSourceCases = .ok (cases', midN) := by - obtain ⟨_, reservedNames, n0, cases', midN, hConcrete, hLowerCases⟩ := - simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default_sourceLowered - have hCombo := - simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete - simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo - exact ⟨reservedNames, n0, cases', midN, hCombo.2.2.1.2, hLowerCases⟩ +theorem generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported_except_mapping_writes + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := by + intro fn hmem + have hCompiled := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions_except_mapping_writes + spec selectors hSupported irContract hCompile + rcases exists_left_of_forall₂_mem_right hCompiled hmem with + ⟨entry, hentryMem, hCompileFn⟩ + have hSelectorEq : + fn.selector = entry.2 := + Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_selector + spec.fields spec.events spec.errors entry.2 entry.1 fn hCompileFn + have hSelectorMem : entry.2 ∈ selectors := by + simpa [SourceSemantics.selectorFunctionPairs] using + (snd_mem_of_mem_zip hentryMem) + rw [hSelectorEq] + exact Nat.lt_trans (hSelectorsRange entry.2 hSelectorMem) + selectorModulus_lt_uint256 -/-- The `Classical.choose`-pinned selector-miss `If` body of the SimpleStorage -native dispatcher equals the singleton list `[nativeRevertZeroZeroStmt]`. -Combines `simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if` with a -fully-pinned concrete-form decomposition of the inner block (where body1 is -also pinned via the WithSwitchIds revert lowering equation), then uses head -injection on the second `If` to extract the body equation. Lets downstream -selector-miss exec proofs invoke `exec_revert_zero_zero_error` directly. -/ -theorem simpleStorageNativeDispatcher_if1Body_eq : - simpleStorageNativeDispatcher_if1Body = - [Backends.Native.nativeRevertZeroZeroStmt] := by - have hOk := simpleStorageNativeDispatcherStmts_lowering_ok - rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk - obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk - obtain ⟨rest', hLet, hRestLowering⟩ := - lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner - obtain ⟨body1', _, rest'', hIf1, hBody1, hRest1⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering - obtain ⟨body2', _, rest''', hIf2, _, hRest2⟩ := - lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 - rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, - Except.ok.injEq, Prod.mk.injEq] at hRest2 - obtain ⟨hNil, _⟩ := hRest2 - subst hNil - have hDef : - Compiler.CodegenCommon.defaultDispatchCase - (none : Option Compiler.IREntrypoint) - (none : Option Compiler.IREntrypoint) = - [Yul.YulStmt.expr - (Yul.YulExpr.call "revert" [Yul.YulExpr.lit 0, Yul.YulExpr.lit 0])] := - rfl - rw [hDef, lowerStmtsNativeWithSwitchIds_revert_zero_zero, - Except.ok.injEq, Prod.mk.injEq] at hBody1 - obtain ⟨hBody1Eq, _⟩ := hBody1 - subst hBody1Eq - rw [hIf2] at hIf1 - rw [hIf1] at hLet - have hCombo := - simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hLet - simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo - exact hCombo.2.1.2 +theorem generatedRuntimeFunctionSelectorsSelectorRange_of_compile_ok_supported_except_mapping_writes + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) : + ∀ fn, fn ∈ irContract.functions → + fn.selector < Compiler.Constants.selectorModulus := by + intro fn hmem + have hCompiled := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions_except_mapping_writes + spec selectors hSupported irContract hCompile + rcases exists_left_of_forall₂_mem_right hCompiled hmem with + ⟨entry, hentryMem, hCompileFn⟩ + have hSelectorEq : + fn.selector = entry.2 := + Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_selector + spec.fields spec.events spec.errors entry.2 entry.1 fn hCompileFn + have hSelectorMem : entry.2 ∈ selectors := by + simpa [SourceSemantics.selectorFunctionPairs] using + (snd_mem_of_mem_zip hentryMem) + rw [hSelectorEq] + exact hSelectorsRange entry.2 hSelectorMem -/-- Closed-form selector-miss revert exec for the SimpleStorage native -dispatcher's first `If` body. The body is the singleton list -`[nativeRevertZeroZeroStmt]` (by `simpleStorageNativeDispatcher_if1Body_eq`), -so a `.Block` execution at any fuel `≥ 7` peels the head via -`exec_block_cons_error` and reduces to `exec_revert_zero_zero_error`, -producing EVMYulLean's `Revert` exception. Self-contained — no premise on -state/eval is needed because the body has no side effects before the revert. +private theorem selector_eq_of_find_function_by_selector + {functions : List IRFunction} {selector : Nat} {fn : IRFunction} + (hFind : functions.find? (fun fn => fn.selector == selector) = some fn) : + fn.selector = selector := by + induction functions with + | nil => + simp at hFind + | cons head tail ih => + by_cases hHead : head.selector = selector + · simp [hHead] at hFind + exact hFind ▸ hHead + · simp [hHead] at hFind + exact ih hFind -This is the per-statement halt lemma the selector-miss dispatcher proof will -chain after the `let __has_selector := …` and `if iszero(__has_selector)` -peels: once `__has_selector = 0` is established, the if guard fires, and this -lemma immediately closes the dispatcher result as `.error Revert`. -/ -theorem exec_block_simpleStorageNativeDispatcher_if1Body_revert - (fuel : Nat) (state : EvmYul.Yul.State) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) : - EvmYul.Yul.exec (fuel + 7) (.Block simpleStorageNativeDispatcher_if1Body) - codeOverride state = - .error EvmYul.Yul.Exception.Revert := by - rw [simpleStorageNativeDispatcher_if1Body_eq] - exact Compiler.Proofs.YulGeneration.Backends.Native.exec_block_cons_error - (fuel + 6) - Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt - [] codeOverride state EvmYul.Yul.Exception.Revert - (Compiler.Proofs.YulGeneration.Backends.Native.exec_revert_zero_zero_error - fuel state codeOverride) +theorem selectedGeneratedFunctionSelectorRange_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + tx.functionSelector < Compiler.Constants.selectorModulus := by + have hFnRange := + generatedRuntimeFunctionSelectorsSelectorRange_of_compile_ok_supported + hCompile hSupported hSelectorsRange fn (List.mem_of_find?_eq_some hFind) + have hEq := selector_eq_of_find_function_by_selector hFind + simpa [hEq] using hFnRange -/-- Composed dispatcher peel exposing the SimpleStorage native dispatcher's -inner three-statement block exec as a singleton `lowerNativeSwitchBlock` exec -on the post-Let state. Chains the named let/if/if normalization with the -let-selector / if1-skip / if2-take peel -(`exec_block_letSelector_if1Skip_if2Take_initialState_fuel`, which discharges -calldatasize ≥ 4 via `hNoWrap` so the let binds `__has_selector` to 1) and the -just-landed `simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_exists` -characterization, leaving the dispatcher inner-block exec equal to a single -lowered switch-block exec on -`(nativeSwitchInitialOkState).insert "__has_selector" 1`. The switch-id, -lowered case bodies, and lowered default body remain existential — they are -fixed by the concrete `simpleStorageIRContract.functions` list and threaded -through later case-dispatch peels using -`exec_lowerNativeSwitchBlock_simpleStorageConcrete_*` lemmas. -/ -theorem exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_exec - (fuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : - ∃ (switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (default' : List EvmYul.Yul.Ast.Stmt), - EvmYul.Yul.exec (fuel + 12) - (.Block simpleStorageNativeDispatcherInnerStmts) - (some contract) - (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - contract tx storage observableSlots) = - EvmYul.Yul.exec (fuel + 8) - (.Block - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' default']) - (some contract) - ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - contract tx storage observableSlots).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)) := by - obtain ⟨switchId, cases', default', hIf2Body⟩ := - simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_exists - refine ⟨switchId, cases', default', ?_⟩ - rw [simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if, - simpleStorageNativeDispatcher_letValue_eq, - simpleStorageNativeDispatcher_if1Cond_eq, - simpleStorageNativeDispatcher_if2Cond_eq, hIf2Body] - exact Backends.Native.exec_block_letSelector_if1Skip_if2Take_initialState_fuel - fuel contract tx storage observableSlots "__has_selector" - simpleStorageNativeDispatcher_if1Body - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' default'] - hNoWrap +theorem selectedGeneratedFunctionSelectorRange_of_compile_ok_supported_except_mapping_writes + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + tx.functionSelector < Compiler.Constants.selectorModulus := by + have hFnRange := + generatedRuntimeFunctionSelectorsSelectorRange_of_compile_ok_supported_except_mapping_writes + hCompile hSupported hSelectorsRange fn (List.mem_of_find?_eq_some hFind) + have hEq := selector_eq_of_find_function_by_selector hFind + simpa [hEq] using hFnRange -/-- Strengthened companion of `exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_exec` -where the lowered default body of the inner switch is pinned to -`[nativeRevertZeroZeroStmt]`. Uses -`simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_exists` -in place of the unpinned existential variant. -/ -theorem exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec - (fuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : - ∃ (switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), - EvmYul.Yul.exec (fuel + 12) - (.Block simpleStorageNativeDispatcherInnerStmts) - (some contract) - (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - contract tx storage observableSlots) = - EvmYul.Yul.exec (fuel + 8) - (.Block - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' - [Backends.Native.nativeRevertZeroZeroStmt]]) - (some contract) - ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - contract tx storage observableSlots).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)) := by - obtain ⟨switchId, cases', hIf2Body⟩ := - simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_exists - refine ⟨switchId, cases', ?_⟩ - rw [simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if, - simpleStorageNativeDispatcher_letValue_eq, - simpleStorageNativeDispatcher_if1Cond_eq, - simpleStorageNativeDispatcher_if2Cond_eq, hIf2Body] - exact Backends.Native.exec_block_letSelector_if1Skip_if2Take_initialState_fuel - fuel contract tx storage observableSlots "__has_selector" - simpleStorageNativeDispatcher_if1Body - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' - [Backends.Native.nativeRevertZeroZeroStmt]] - hNoWrap +/-- Selector-dispatched source functions in a `SupportedSpec` expose their +body-level `SupportedStmtList` witness directly. -/-- Source-lowered companion of `exec_block_..._eq_lowerNativeSwitchBlock_revert_default_exec`: -the inner-stmts-to-lowered-switch-block exec equation additionally exposes -`switchId = freshNativeSwitchId reservedNames n0` and the source-cases lowering -equation linking `simpleStorageBuildSwitchSourceCases` to the lowered `cases'`. -Built by switching the underlying `if2Body` decomposition to its sourceLowered -companion. -/ -theorem exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - (fuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : - ∃ (reservedNames : List String) (n0 : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), - EvmYul.Yul.exec (fuel + 12) - (.Block simpleStorageNativeDispatcherInnerStmts) - (some contract) - (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - contract tx storage observableSlots) = - EvmYul.Yul.exec (fuel + 8) - (.Block - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - (Backends.freshNativeSwitchId reservedNames n0) cases' - [Backends.Native.nativeRevertZeroZeroStmt]]) - (some contract) - ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - contract tx storage observableSlots).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)) ∧ - Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames - (Backends.freshNativeSwitchId reservedNames n0 + 1) - simpleStorageBuildSwitchSourceCases = .ok (cases', midN) := by - obtain ⟨reservedNames, n0, cases', midN, hIf2Body, hLowerCases⟩ := - simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_sourceLowered - refine ⟨reservedNames, n0, cases', midN, ?_, hLowerCases⟩ - rw [simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if, - simpleStorageNativeDispatcher_letValue_eq, - simpleStorageNativeDispatcher_if1Cond_eq, - simpleStorageNativeDispatcher_if2Cond_eq, hIf2Body] - exact Backends.Native.exec_block_letSelector_if1Skip_if2Take_initialState_fuel - fuel contract tx storage observableSlots "__has_selector" - simpleStorageNativeDispatcher_if1Body - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - (Backends.freshNativeSwitchId reservedNames n0) cases' - [Backends.Native.nativeRevertZeroZeroStmt]] - hNoWrap +This is the source-side entry point for the generated-runtime closure proofs: +the witness is pulled from +`hSupported.supportedFunctionOfSelectorDispatched ... .body.stmtList` for each +function paired with a selector. -/ +theorem generatedRuntimeSupportedStmtList_of_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + SupportedStmtList spec.fields (entry.1.params.map (·.name)) + entry.1.body := by + intro entry hentry + have hfn : entry.1 ∈ selectorDispatchedFunctions spec := by + simpa [SourceSemantics.selectorFunctionPairs] using + (List.of_mem_zip hentry).1 + exact (hSupported.supportedFunctionOfSelectorDispatched hfn).body.stmtList -/-- Bridge-level lift of the inner-block-to-lowerNativeSwitchBlock combinator: -chains `simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec` with the -just-landed `_innerStmts_eq_lowerNativeSwitchBlock_exec`, so the bridge's -`contractDispatcherExecResult` at fuel `peeledFuel + 14` reduces to an exec of -a singleton lowered-switch block at fuel `peeledFuel + 8` on -`(initialOk).insert "__has_selector" 1`. -/ -theorem simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_exec - (peeledFuel : Nat) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : - ∃ (switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (default' : List EvmYul.Yul.Ast.Stmt), - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (peeledFuel + 14) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = - EvmYul.Yul.exec (peeledFuel + 8) - (.Block - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' default']) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)) := by - obtain ⟨switchId, cases', default', hExec⟩ := - exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_exec - peeledFuel Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots hNoWrap - refine ⟨switchId, cases', default', ?_⟩ - have hShape : peeledFuel + 14 = - Nat.succ (Nat.succ (Nat.succ (peeledFuel + 11))) := by omega - rw [hShape, simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec - (peeledFuel + 11) tx storage observableSlots] - exact hExec +/-- Direct source-function form of the supported body statement-list witness. -/-- Strengthened companion of `simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_exec` -with the lowered default body pinned to `[nativeRevertZeroZeroStmt]`. Chains -the `_innerBlock_exec` combinator with the strengthened -`_innerStmts_eq_lowerNativeSwitchBlock_revert_default_exec`. This is the entry -point that downstream selector-miss bridge proofs will plug into the new -store-parametric `exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_fuel` -endpoint. -/ -theorem simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec - (peeledFuel : Nat) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : - ∃ (switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (peeledFuel + 14) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = - EvmYul.Yul.exec (peeledFuel + 8) - (.Block - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' - [Backends.Native.nativeRevertZeroZeroStmt]]) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)) := by - obtain ⟨switchId, cases', hExec⟩ := - exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec - peeledFuel Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots hNoWrap - refine ⟨switchId, cases', ?_⟩ - have hShape : peeledFuel + 14 = - Nat.succ (Nat.succ (Nat.succ (peeledFuel + 11))) := by omega - rw [hShape, simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec - (peeledFuel + 11) tx storage observableSlots] - exact hExec +This is the raw `SupportedSpec.functions ... body.stmtList` entry point; the +selector-pair theorem above is the generated-runtime specialization. -/ +theorem supportedFunctionSupportedStmtList_of_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) : + ∀ fn, fn ∈ spec.functions → + SupportedStmtList spec.fields (fn.params.map (·.name)) fn.body := by + intro fn hmem + exact (hSupported.functions fn hmem).body.stmtList -/-- Source-lowered companion of `_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec`: -the dispatcher-level reduction additionally exposes -`switchId = freshNativeSwitchId reservedNames n0` and the source-cases lowering -equation. This is the form selector-miss closed-form proofs will consume — -they open the existential, then chain `lowerSwitchCasesNativeWithSwitchIds_tags_eq` -to lift source-level selector facts (decided from `simpleStorageIRContract`) -into the lowered `cases'.find?` results required by the `_via_reduction` -endpoint. -/ -theorem simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - (peeledFuel : Nat) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : - ∃ (reservedNames : List String) (n0 : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (peeledFuel + 14) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = - EvmYul.Yul.exec (peeledFuel + 8) - (.Block - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - (Backends.freshNativeSwitchId reservedNames n0) cases' - [Backends.Native.nativeRevertZeroZeroStmt]]) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)) ∧ - Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames - (Backends.freshNativeSwitchId reservedNames n0 + 1) - simpleStorageBuildSwitchSourceCases = .ok (cases', midN) := by - obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := - exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - peeledFuel Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots hNoWrap - refine ⟨reservedNames, n0, cases', midN, ?_, hLowerCases⟩ - have hShape : peeledFuel + 14 = - Nat.succ (Nat.succ (Nat.succ (peeledFuel + 11))) := by omega - rw [hShape, simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec - (peeledFuel + 11) tx storage observableSlots] - exact hExec +private theorem stmtListTouchesUnsupportedStateSurface_append + (pfx sfx : List CompilationModel.Stmt) : + stmtListTouchesUnsupportedStateSurface (pfx ++ sfx) = + (stmtListTouchesUnsupportedStateSurface pfx || + stmtListTouchesUnsupportedStateSurface sfx) := by + induction pfx with + | nil => + simp [stmtListTouchesUnsupportedStateSurface] + | cons stmt rest ih => + simp [stmtListTouchesUnsupportedStateSurface, ih, Bool.or_assoc] -/-- Bridge-level selector-miss endpoint, parametric in `cases'` and `switchId`: -composes the harness-level -`exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error` with -the strengthened-reduction equation at the matching fuel -`peeledFuel = fuel + cases'.length + 5`. The reduction equation is taken as a -hypothesis so the caller can pin a specific `cases'` (e.g. by opening the -existential of `_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec`) -without forcing the fuel parameter to depend on a not-yet-bound term. This is -the direct selector-miss discharge composing into -`contractDispatcherExecResult = .error Revert`. -/ -theorem simpleStorageNativeContract_dispatcherExec_selectorMiss_revert_via_reduction - (fuel selector switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hFind : cases'.find? (fun entry => entry.1 == selector) = none) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size) - (hReduction : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + cases'.length + 19) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = - EvmYul.Yul.exec (fuel + cases'.length + 13) - (.Block - [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" - [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' - [Backends.Native.nativeRevertZeroZeroStmt]]) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots).insert "__has_selector" - (EvmYul.UInt256.ofNat 1))) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + cases'.length + 19) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = - .error EvmYul.Yul.Exception.Revert := by - rw [hReduction] - exact Backends.Native.exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error - fuel selector switchId cases' - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots hSelector hFind hSelectorRange hTagsRange +private theorem stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites_append + (pfx sfx : List CompilationModel.Stmt) : + stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites (pfx ++ sfx) = + (stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites pfx || + stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites sfx) := by + induction pfx with + | nil => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites] + | cons stmt rest ih => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, ih, + Bool.or_assoc] -/-- The source-level switch cases emitted by `buildSwitch` for SimpleStorage -project to the concrete two-element selector list `[0x6057361d, 0x2e64cec1]`. -This anchors source-level selector-miss reasoning at the IR layer so the rest -of the dispatcher proof can stay parametric in `cases'`. -/ -theorem simpleStorageBuildSwitchSourceCases_map_fst : - simpleStorageBuildSwitchSourceCases.map (·.1) = - [(0x6057361d : Nat), (0x2e64cec1 : Nat)] := rfl +private theorem stmtListTouchesUnsupportedEffectSurface_append + (pfx sfx : List CompilationModel.Stmt) : + stmtListTouchesUnsupportedEffectSurface (pfx ++ sfx) = + (stmtListTouchesUnsupportedEffectSurface pfx || + stmtListTouchesUnsupportedEffectSurface sfx) := by + induction pfx with + | nil => + simp [stmtListTouchesUnsupportedEffectSurface] + | cons stmt rest ih => + simp [stmtListTouchesUnsupportedEffectSurface, ih, Bool.or_assoc] -/-- Source-cases find?-none for SimpleStorage: the selector-miss assumption -`sel ≠ 0x6057361d ∧ sel ≠ 0x2e64cec1` (the two SimpleStorage IR selectors) -suffices to discharge `find?` on the buildSwitch-emitted source case list. -This is the source-level half of the selector-miss closed form. -/ -theorem simpleStorageBuildSwitchSourceCases_find?_none {sel : Nat} - (h1 : sel ≠ 0x6057361d) (h2 : sel ≠ 0x2e64cec1) : - simpleStorageBuildSwitchSourceCases.find? (fun entry => entry.1 == sel) = - none := by - show ([_, _] : List _).find? _ = none - simp only [List.find?_cons, List.find?_nil] - have hb1 : ((0x6057361d : Nat) == sel) = false := - beq_eq_false_iff_ne.mpr (Ne.symm h1) - have hb2 : ((0x2e64cec1 : Nat) == sel) = false := - beq_eq_false_iff_ne.mpr (Ne.symm h2) - rw [hb1, hb2] +/-- Generic source-body closure from `SupportedStmtList` to +`BridgedSafeStmts` on the helper-free external-call surface. -/-- All tags in the buildSwitch-emitted source cases for SimpleStorage are -strictly less than `EvmYul.UInt256.size = 2^256`. The two source selectors -(`0x6057361d`, `0x2e64cec1`) both fit in 32 bits, far below the EVM word -modulus. -/ -theorem simpleStorageBuildSwitchSourceCases_tags_lt_uint256_size : - ∀ tag body, (tag, body) ∈ simpleStorageBuildSwitchSourceCases → - tag < EvmYul.UInt256.size := by - intro tag body h - simp only [simpleStorageBuildSwitchSourceCases, simpleStorageIRContract, - List.map_cons, List.map_nil, List.mem_cons, Prod.mk.injEq, - List.not_mem_nil, or_false] at h - rcases h with ⟨rfl, _⟩ | ⟨rfl, _⟩ <;> decide +The state/effect surface-closure premises are the exact negative witnesses +needed to rule out the `SupportedStmtList` constructors that are still outside +the current EVMYulLean bridged-safe fragment. -/ +theorem supportedStmtList_safe_of_state_effect_closed + {fields : List CompilationModel.Field} + {errors : List CompilationModel.ErrorDef} + {dynamicSource : CompilationModel.DynamicDataSource} + {scope : List String} {stmts : List CompilationModel.Stmt} + (hSupported : SupportedStmtList fields scope stmts) + (hState : stmtListTouchesUnsupportedStateSurface stmts = false) + (hEffects : stmtListTouchesUnsupportedEffectSurface stmts = false) : + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + fields errors dynamicSource [] false stmts := by + induction hSupported with + | compileCore hCore => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_externalCompileCore + (errors := errors) (dynamicSource := dynamicSource) hCore + | terminalCore hCore => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_externalTerminalCore + (errors := errors) (dynamicSource := dynamicSource) hCore + | setStorageSingleSlot hValue _ hFind => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStorageSingleSlot_of_exprCompileCore + (errors := errors) (dynamicSource := dynamicSource) hValue hFind + | setStorageAddrSingleSlot hValue _ hFind => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStorageAddrSingleSlot_of_exprCompileCore + (errors := errors) (dynamicSource := dynamicSource) hValue hFind + | mstoreSingle hOffset _ hValue _ => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_mstoreSingle_of_exprCompileCore + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + hOffset hValue + | tstoreSingle hOffset _ hValue _ => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_tstoreSingle_of_exprCompileCore + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + hOffset hValue + | letStorageField => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letStorageAddrField => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | assignStorageField => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | assignStorageAddrField => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | emitEvent => + simp [stmtListTouchesUnsupportedEffectSurface, + stmtTouchesUnsupportedEffectSurface] at hEffects + | letMappingField => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letMappingWordField => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letMappingUintField => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letMappingPackedWordField => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letMapping2Field => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letMapping2WordField => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letStructMemberField => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letStructMember2Field => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | setMappingUintSingle => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface] at hState + | setMappingChainSingle => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface] at hState + | setMappingSingle => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface] at hState + | setMappingWordSingle => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface] at hState + | setMappingPackedWordSingle => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface] at hState + | setStructMemberSingle => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface] at hState + | setMapping2Single => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface] at hState + | setMapping2WordSingle => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface] at hState + | setStructMember2Single => + simp [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface] at hState + | requireClause clause _ ih => + simpa using + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts.append + (Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_requireGuardFamilyClause + (fields := fields) (errors := errors) + (dynamicSource := dynamicSource) + clause) + (ih + (by + simpa [stmtListTouchesUnsupportedStateSurface, + stmtTouchesUnsupportedStateSurface, + Verity.Core.Free.RequireLiteralGuardFamilyClause.toStmt, + exprTouchesUnsupportedStateSurface] using + (Bool.or_eq_false_iff.mp hState).2) + (by + simpa [stmtListTouchesUnsupportedEffectSurface, + stmtTouchesUnsupportedEffectSurface, + Verity.Core.Free.RequireLiteralGuardFamilyClause.toStmt] using + (Bool.or_eq_false_iff.mp hEffects).2)) + | iteTerminal hCond hBound hThen hElse => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_externalTerminalCore + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (FunctionBody.StmtListTerminalCore.ite hCond hBound hThen hElse + (FunctionBody.StmtListCompileCore.nil)) + | append hpfx hsfx ihPfx ihSfx => + rw [stmtListTouchesUnsupportedStateSurface_append] at hState + rw [stmtListTouchesUnsupportedEffectSurface_append] at hEffects + exact Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts.append + (ihPfx (Bool.or_eq_false_iff.mp hState).1 + (Bool.or_eq_false_iff.mp hEffects).1) + (ihSfx (Bool.or_eq_false_iff.mp hState).2 + (Bool.or_eq_false_iff.mp hEffects).2) -/-- Shape characterization for the lowered SimpleStorage source switch cases. +/-- Generic source-body closure from `SupportedStmtList` to `BridgedSafeStmts` +when mapping writes are allowed by the state-surface gate and supplied with the +body-local slot-safety witness used by the Tier 2 mapping-write theorem. -Exactly two entries — the SimpleStorage IR selectors `0x6057361d` and -`0x2e64cec1` — flow through `lowerSwitchCasesNativeWithSwitchIds`, so the -output `cases'` is forced to a two-element shape with lowered bodies. Each -selector tag is preserved unchanged by the lowering; only the case bodies -are recursively lowered. Hit-case proofs consume this shape to convert the -parametric `cases'` (opened from the `_sourceLowered` existential) into the -concrete `[(0x6057361d, _), (0x2e64cec1, _)]` form that matches the -generic harness lemmas like -`exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_fuel`. -/ -theorem simpleStorageBuildSwitchSourceCases_lowered_shape - (reservedNames : List String) (nextSwitchId final : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (hLower : - Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames nextSwitchId - simpleStorageBuildSwitchSourceCases = .ok (cases', final)) : - ∃ storeBody' retrieveBody', - cases' = [(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] := by - have hTags := Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq - _ _ _ _ _ hLower - have hLen := Backends.lowerSwitchCasesNativeWithSwitchIds_length_eq - _ _ _ _ _ hLower - rw [simpleStorageBuildSwitchSourceCases_map_fst] at hTags - match cases', hLen, hTags with - | [(t1, b1), (t2, b2)], _, hTags => - simp only [List.map_cons, List.map_nil, List.cons.injEq, and_true] at hTags - obtain ⟨ht1, ht2⟩ := hTags - exact ⟨b1, b2, by rw [ht1, ht2]⟩ +This is the constructor-facing companion to +`supportedStmtList_safe_of_state_effect_closed`: it does not pretend the +surface predicate itself proves mapping layout facts, but consumes exactly the +extra per-statement facts needed for the mapping-write constructors. -/ +theorem supportedStmtList_safe_of_state_except_mapping_writes_stmt_safety + {fields : List CompilationModel.Field} + {errors : List CompilationModel.ErrorDef} + {dynamicSource : CompilationModel.DynamicDataSource} + {scope : List String} {stmts : List CompilationModel.Stmt} + (hSupported : SupportedStmtList fields scope stmts) + (hSafety : ∀ stmt ∈ stmts, StmtMappingWriteSlotSafe fields stmt) + (hState : + stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites stmts = false) + (hEffects : stmtListTouchesUnsupportedEffectSurface stmts = false) : + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + fields errors dynamicSource [] false stmts := by + induction hSupported with + | compileCore hCore => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_externalCompileCore + (errors := errors) (dynamicSource := dynamicSource) hCore + | terminalCore hCore => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_externalTerminalCore + (errors := errors) (dynamicSource := dynamicSource) hCore + | setStorageSingleSlot hValue _ hFind => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStorageSingleSlot_of_exprCompileCore + (errors := errors) (dynamicSource := dynamicSource) hValue hFind + | setStorageAddrSingleSlot hValue _ hFind => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStorageAddrSingleSlot_of_exprCompileCore + (errors := errors) (dynamicSource := dynamicSource) hValue hFind + | mstoreSingle hOffset _ hValue _ => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_mstoreSingle_of_exprCompileCore + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + hOffset hValue + | tstoreSingle hOffset _ hValue _ => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_tstoreSingle_of_exprCompileCore + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + hOffset hValue + | letStorageField => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letStorageAddrField => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | assignStorageField => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | assignStorageAddrField => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | emitEvent => + simp [stmtListTouchesUnsupportedEffectSurface, + stmtTouchesUnsupportedEffectSurface] at hEffects + | letMappingField => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letMappingWordField => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letMappingUintField => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letMappingPackedWordField => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letMapping2Field => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letMapping2WordField => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letStructMemberField => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | letStructMember2Field => + simp [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurface, exprTouchesUnsupportedStateSurface] at hState + | @setMappingUintSingle scope fieldName key value slot hKey _ hValue _ _ => + rcases hSafety (.setMappingUint fieldName key value) (by simp) with + ⟨safeSlot, _hFind, hMapping, hSlots, _hSlotSafety⟩ + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingUintSingleSlot + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping hSlots + | @setMappingChainSingle scope fieldName keys value slot hKeys _ hValue _ _ => + rcases hSafety (.setMappingChain fieldName keys value) (by simp) with + ⟨safeSlot, _hFind, hMapping, hSlots, _hSlotSafety⟩ + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingChainSingleSlot + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) + (fun key hMem => + Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore + (hKeys key hMem)) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping hSlots + | @setMappingSingle scope fieldName key value slot hKey _ hValue _ _ => + rcases hSafety (.setMapping fieldName key value) (by simp) with + ⟨safeSlot, _hFind, hMapping, hSlots, _hSlotSafety⟩ + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingSingleSlot + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping hSlots + | @setMappingWordSingle scope fieldName key value wordOffset slot hKey _ hValue _ _ => + rcases hSafety (.setMappingWord fieldName key wordOffset value) (by simp) with + ⟨safeSlot, _hFind, hMapping, hSlots, _hSlotSafety⟩ + by_cases hZero : wordOffset = 0 + · exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingWordSingleSlot + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping hSlots hZero + · exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingWordSingleSlotNonzero + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping hSlots hZero + | @setMappingPackedWordSingle scope fieldName key value wordOffset slot packed + hKey _ hValue _ _ _ _ _ hPacked _ => + rcases hSafety (.setMappingPackedWord fieldName key wordOffset packed value) (by simp) with + ⟨safeSlot, _hFind, hMapping, hSlots, _hSlotSafety⟩ + by_cases hZero : wordOffset = 0 + · exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingPackedWordSingleSlot + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping hSlots hZero hPacked + · exact Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts.mappingPackedWordNonzero + (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact Compiler.Proofs.YulGeneration.Backends.BridgedSourceMappingPackedWordNonzeroStmt.setMappingPackedWord + fieldName packed + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping hSlots hZero hPacked) + | @setStructMemberSingle scope fieldName memberName key value slot wordOffset members + hKey _ hValue _ _ _ _ => + rcases hSafety (.setStructMember fieldName key memberName value) (by simp) with + ⟨safeSlot, safeWordOffset, safeMembers, _hFind, hMembers, + hFindMember, hMapping, hNotMapping2, hSlots, _hSlotSafety⟩ + by_cases hZero : safeWordOffset = 0 + · exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStructMemberSingleSlot + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) (memberName := memberName) + (members := safeMembers) + (member := { name := memberName, wordOffset := safeWordOffset, packed := none }) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hNotMapping2 hMembers hFindMember rfl hZero hMapping hSlots + · exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStructMemberSingleSlotNonzero + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) (memberName := memberName) + (members := safeMembers) + (member := { name := memberName, wordOffset := safeWordOffset, packed := none }) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hNotMapping2 hMembers hFindMember rfl hZero hMapping hSlots + | @setMapping2Single scope fieldName key1 key2 value slot hKey1 _ hKey2 _ hValue _ _ => + rcases hSafety (.setMapping2 fieldName key1 key2 value) (by simp) with + ⟨safeSlot, _hFind, hMapping2, hSlots, _hSlotSafety⟩ + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMapping2SingleSlot + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey1) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey2) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping2 hSlots + | @setMapping2WordSingle scope fieldName key1 key2 value wordOffset slot + hKey1 _ hKey2 _ hValue _ _ => + rcases hSafety (.setMapping2Word fieldName key1 key2 wordOffset value) (by simp) with + ⟨safeSlot, _hFind, hMapping2, hSlots, _hSlotSafety⟩ + by_cases hZero : wordOffset = 0 + · exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMapping2WordSingleSlot + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey1) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey2) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping2 hSlots hZero + · exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMapping2WordSingleSlotNonzero + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey1) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey2) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping2 hSlots hZero + | @setStructMember2Single scope fieldName memberName key1 key2 value slot wordOffset members + hKey1 _ hKey2 _ hValue _ _ _ _ => + rcases hSafety (.setStructMember2 fieldName key1 key2 memberName value) (by simp) with + ⟨safeSlot, safeWordOffset, safeMembers, _hFind, hMembers, + hFindMember, hMapping2, hSlots, _hSlotSafety⟩ + by_cases hZero : safeWordOffset = 0 + · exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStructMember2SingleSlot + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) (memberName := memberName) + (members := safeMembers) + (member := { name := memberName, wordOffset := safeWordOffset, packed := none }) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey1) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey2) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping2 hMembers hFindMember rfl hZero hSlots + · exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStructMember2SingleSlotNonzero + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (field := fieldName) (slot := safeSlot) (memberName := memberName) + (members := safeMembers) + (member := { name := memberName, wordOffset := safeWordOffset, packed := none }) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey1) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hKey2) + (Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore hValue) + hMapping2 hMembers hFindMember rfl hZero hSlots + | @requireClause scope clause rest _ ih => + have hTailSafety : + ∀ stmt ∈ rest, StmtMappingWriteSlotSafe fields stmt := by + intro stmt hMem + exact hSafety stmt (by simp [hMem]) + simpa using + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts.append + (Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_requireGuardFamilyClause + (fields := fields) (errors := errors) + (dynamicSource := dynamicSource) + clause) + (ih hTailSafety + (by + simpa [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites, + stmtTouchesUnsupportedStateSurfaceExceptMappingWrites, + Verity.Core.Free.RequireLiteralGuardFamilyClause.toStmt, + stmtTouchesUnsupportedStateSurface, + exprTouchesUnsupportedStateSurface] using + (Bool.or_eq_false_iff.mp hState).2) + (by + simpa [stmtListTouchesUnsupportedEffectSurface, + stmtTouchesUnsupportedEffectSurface, + Verity.Core.Free.RequireLiteralGuardFamilyClause.toStmt] using + (Bool.or_eq_false_iff.mp hEffects).2)) + | iteTerminal hCond hBound hThen hElse => + exact Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_externalTerminalCore + (fields := fields) (errors := errors) (dynamicSource := dynamicSource) + (FunctionBody.StmtListTerminalCore.ite hCond hBound hThen hElse + (FunctionBody.StmtListCompileCore.nil)) + | @append scope pfx sfx hpfx hsfx ihPfx ihSfx => + rw [stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites_append] at hState + rw [stmtListTouchesUnsupportedEffectSurface_append] at hEffects + have hSafetyPfx : ∀ stmt ∈ pfx, StmtMappingWriteSlotSafe fields stmt := by + intro stmt hMem + exact hSafety stmt (by simp [hMem]) + have hSafetySfx : ∀ stmt ∈ sfx, StmtMappingWriteSlotSafe fields stmt := by + intro stmt hMem + exact hSafety stmt (by simp [hMem]) + exact Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts.append + (ihPfx hSafetyPfx (Bool.or_eq_false_iff.mp hState).1 + (Bool.or_eq_false_iff.mp hEffects).1) + (ihSfx hSafetySfx (Bool.or_eq_false_iff.mp hState).2 + (Bool.or_eq_false_iff.mp hEffects).2) -/-- Lowered native body shape of the `store(uint256)` selector arm of the -SimpleStorage source switch cases (leading `.Block []` from the `dispatchBody` -comment, followed by callvalue/calldatasize guards and the calldataload/ -sstore/stop primitive sequence). Pinning this lets downstream hit-case proofs -specialize to a fixed concrete body instead of carrying a parametric -`storeBody'`. -/ -def simpleStorageLoweredStoreCaseBody : List EvmYul.Yul.Ast.Stmt := - [EvmYul.Yul.Ast.Stmt.Block [], - .If (Backends.lowerExprNative (.call "callvalue" [])) - [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], - .If (Backends.lowerExprNative - (.call "lt" [.call "calldatasize" [], .lit 36])) - [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], - .Let ["value"] (some (Backends.lowerExprNative - (.call "calldataload" [.lit 4]))), - .ExprStmtCall (Backends.lowerExprNative - (.call "sstore" [.lit 0, .ident "value"])), - .ExprStmtCall (Backends.lowerExprNative (.call "stop" []))] +/-- Every selector-dispatched source function in a `SupportedSpec` has a +`BridgedSafeStmts` body witness. -/-- Lowered native body shape of the `retrieve()` selector arm of the -SimpleStorage source switch cases. Mirrors `simpleStorageLoweredStoreCaseBody` -for the source `mstore(0, sload(0)); return(0, 32)` body. -/ -def simpleStorageLoweredRetrieveCaseBody : List EvmYul.Yul.Ast.Stmt := - [EvmYul.Yul.Ast.Stmt.Block [], - .If (Backends.lowerExprNative (.call "callvalue" [])) - [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], - .If (Backends.lowerExprNative - (.call "lt" [.call "calldatasize" [], .lit 4])) - [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], - .ExprStmtCall (Backends.lowerExprNative - (.call "mstore" [.lit 0, .call "sload" [.lit 0]])), - .ExprStmtCall (Backends.lowerExprNative - (.call "return" [.lit 0, .lit 32]))] +This composes the body `SupportedStmtList` witness from `SupportedSpec` with +the body-level state/effect closure witnesses stored alongside it. -/ +theorem generatedRuntimeSafeBodies_of_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body := by + intro entry hentry + have hfn : entry.1 ∈ selectorDispatchedFunctions spec := by + simpa [SourceSemantics.selectorFunctionPairs] using + (List.of_mem_zip hentry).1 + exact supportedStmtList_safe_of_state_effect_closed + (hSupported.supportedFunctionOfSelectorDispatched hfn).body.stmtList + (hSupported.supportedFunctionOfSelectorDispatched hfn).body.state.surfaceClosed + (hSupported.supportedFunctionOfSelectorDispatched hfn).body.effects.surfaceClosed -/-- 5-statement tail of `simpleStorageLoweredStoreCaseBody`, with the leading -no-op `.Block []` (from the `dispatchBody` source comment) stripped. -/ -def simpleStorageLoweredStoreCaseBodyTail : List EvmYul.Yul.Ast.Stmt := - [.If (Backends.lowerExprNative (.call "callvalue" [])) - [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], - .If (Backends.lowerExprNative - (.call "lt" [.call "calldatasize" [], .lit 36])) - [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], - .Let ["value"] (some (Backends.lowerExprNative - (.call "calldataload" [.lit 4]))), - .ExprStmtCall (Backends.lowerExprNative - (.call "sstore" [.lit 0, .ident "value"])), - .ExprStmtCall (Backends.lowerExprNative (.call "stop" []))] +/-- Direct source-function closure from `SupportedSpec.functions` to +`BridgedSafeStmts`. -/-- 4-statement tail of `simpleStorageLoweredRetrieveCaseBody`, with the leading -no-op `.Block []` (from the `dispatchBody` source comment) stripped. -/ -def simpleStorageLoweredRetrieveCaseBodyTail : List EvmYul.Yul.Ast.Stmt := - [.If (Backends.lowerExprNative (.call "callvalue" [])) - [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], - .If (Backends.lowerExprNative - (.call "lt" [.call "calldatasize" [], .lit 4])) - [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], - .ExprStmtCall (Backends.lowerExprNative - (.call "mstore" [.lit 0, .call "sload" [.lit 0]])), - .ExprStmtCall (Backends.lowerExprNative - (.call "return" [.lit 0, .lit 32]))] +This theorem is the generic body-level bridge requested by the native proof +pipeline: each source function accepted by `SupportedSpec` has a body admitted +by the `BridgedSafeStmts` whitelist before any compilation/lowering shape is +considered. -/ +theorem supportedFunctionBody_safe_of_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) : + ∀ fn, fn ∈ spec.functions → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false fn.body := by + intro fn hmem + exact supportedStmtList_safe_of_state_effect_closed + (supportedFunctionSupportedStmtList_of_supported hSupported fn hmem) + (hSupported.functions fn hmem).body.state.surfaceClosed + (hSupported.functions fn hmem).body.effects.surfaceClosed -/-- Strip the leading `.Block []` no-op (a `dispatchBody` source-comment -artifact) from the lowered store-case body when proving a `.error err` -obligation. Combines `exec_block_nil_ok` (the empty inner block is a no-op at -positive fuel, returning the input state unchanged) with -`exec_block_cons_tail_error` (a successful head followed by an erroring tail -makes the whole block error). Reduces a 6-statement obligation to a strictly -smaller 5-statement tail obligation. -/ -theorem exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error - (fuel' : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state : EvmYul.Yul.State) (err : EvmYul.Yul.Exception) - (hTail : - EvmYul.Yul.exec (fuel' + 1) - (.Block simpleStorageLoweredStoreCaseBodyTail) codeOverride state = - .error err) : - EvmYul.Yul.exec (fuel' + 2) - (.Block simpleStorageLoweredStoreCaseBody) codeOverride state = - .error err := by - show EvmYul.Yul.exec (Nat.succ (fuel' + 1)) - (.Block (.Block [] :: simpleStorageLoweredStoreCaseBodyTail)) - codeOverride state = .error err - refine Backends.Native.exec_block_cons_tail_error (fuel' + 1) (.Block []) - simpleStorageLoweredStoreCaseBodyTail codeOverride state state err ?_ hTail - exact Backends.Native.exec_block_nil_ok fuel' codeOverride state +/-- Direct source-function closure for the weaker mapping-write-supported +surface. Actual mapping-write statements must still carry the local slot-safety +witness consumed by the Tier 2 body bridge. -/ +theorem supportedFunctionBody_safe_of_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpecExceptMappingWrites spec selectors) : + ∀ fn, fn ∈ spec.functions → + (∀ stmt, stmt ∈ fn.body → StmtMappingWriteSlotSafe spec.fields stmt) → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false fn.body := by + intro fn hmem hSafety + exact supportedStmtList_safe_of_state_except_mapping_writes_stmt_safety + (hSupported.functions fn hmem).body.stmtList + hSafety + (hSupported.functions fn hmem).body.state.surfaceClosed + (hSupported.functions fn hmem).body.effects.surfaceClosed -/-- Retrieve-case dual of -`exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error`. -/ -theorem exec_block_simpleStorageLoweredRetrieveCaseBody_head_strip_error - (fuel' : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state : EvmYul.Yul.State) (err : EvmYul.Yul.Exception) - (hTail : - EvmYul.Yul.exec (fuel' + 1) - (.Block simpleStorageLoweredRetrieveCaseBodyTail) codeOverride state = - .error err) : - EvmYul.Yul.exec (fuel' + 2) - (.Block simpleStorageLoweredRetrieveCaseBody) codeOverride state = - .error err := by - show EvmYul.Yul.exec (Nat.succ (fuel' + 1)) - (.Block (.Block [] :: simpleStorageLoweredRetrieveCaseBodyTail)) - codeOverride state = .error err - refine Backends.Native.exec_block_cons_tail_error (fuel' + 1) (.Block []) - simpleStorageLoweredRetrieveCaseBodyTail codeOverride state state err ?_ hTail - exact Backends.Native.exec_block_nil_ok fuel' codeOverride state +/-- Selector-dispatched source functions in the weaker mapping-write-supported +spec surface have `BridgedSafeStmts` body witnesses when each actual body +mapping-write statement supplies its slot-safety evidence. -/ +theorem generatedRuntimeSafeBodies_of_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body := by + intro entry hentry + have hfn : entry.1 ∈ selectorDispatchedFunctions spec := by + simpa [SourceSemantics.selectorFunctionPairs] using + (List.of_mem_zip hentry).1 + exact supportedStmtList_safe_of_state_except_mapping_writes_stmt_safety + (hSupported.supportedFunctionOfSelectorDispatched hfn).body.stmtList + (hSafety entry hentry) + (hSupported.supportedFunctionOfSelectorDispatched hfn).body.state.surfaceClosed + (hSupported.supportedFunctionOfSelectorDispatched hfn).body.effects.surfaceClosed -/-- 4-statement callvalue-stripped tail of `simpleStorageLoweredStoreCaseBody`, -with both the leading no-op `.Block []` and the leading `if callvalue() {…}` -revert guard removed. Used to further shrink the dispatcher hit-case body-exec -obligation when the transaction has zero `msgValue`. -/ -def simpleStorageLoweredStoreCaseBodyTail2 : List EvmYul.Yul.Ast.Stmt := - [.If (Backends.lowerExprNative - (.call "lt" [.call "calldatasize" [], .lit 36])) - [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], - .Let ["value"] (some (Backends.lowerExprNative - (.call "calldataload" [.lit 4]))), - .ExprStmtCall (Backends.lowerExprNative - (.call "sstore" [.lit 0, .ident "value"])), - .ExprStmtCall (Backends.lowerExprNative (.call "stop" []))] +/-- A supported constructor exposes the same source statement-list witness as +ordinary function bodies, scoped by decoded constructor parameter names. -/ +theorem generatedConstructorSupportedStmtList_of_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) : + ∀ ctor, spec.constructor = some ctor → + SupportedStmtList spec.fields (ctor.params.map (·.name)) ctor.body := by + intro ctor hctor + exact (hSupported.constructor ctor hctor).body.stmtList -/-- 3-statement calldatasize-stripped tail of -`simpleStorageLoweredStoreCaseBodyTail2`, with the argument-length revert guard -removed after proving the transaction supplies the setter argument. -/ -def simpleStorageLoweredStoreCaseBodyTail3 : List EvmYul.Yul.Ast.Stmt := - [.Let ["value"] (some (Backends.lowerExprNative - (.call "calldataload" [.lit 4]))), - .ExprStmtCall (Backends.lowerExprNative - (.call "sstore" [.lit 0, .ident "value"])), - .ExprStmtCall (Backends.lowerExprNative (.call "stop" []))] +/-- Constructor user bodies compile under the memory dynamic-data source. When +their body also satisfies the full state/effect closure surface, the same +generic safe-body bridge used by runtime functions applies. This theorem covers +the user-written constructor body; the initcode argument-copy wrapper remains +outside `BridgedStmts` until the initcode-only builtins are added to the bridge +predicate. -/ +theorem generatedConstructorSafeBody_of_supported_state_closed + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) : + ∀ ctor, spec.constructor = some ctor → + stmtListTouchesUnsupportedStateSurface ctor.body = false → + stmtListTouchesUnsupportedEffectSurface ctor.body = false → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .memory [] false ctor.body := by + intro ctor hctor hState hEffects + exact supportedStmtList_safe_of_state_effect_closed + (dynamicSource := .memory) + (generatedConstructorSupportedStmtList_of_supported hSupported ctor hctor) + hState hEffects -/-- 3-statement callvalue-stripped tail of `simpleStorageLoweredRetrieveCaseBody`. -/ -def simpleStorageLoweredRetrieveCaseBodyTail2 : List EvmYul.Yul.Ast.Stmt := - [.If (Backends.lowerExprNative - (.call "lt" [.call "calldatasize" [], .lit 4])) - [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], - .ExprStmtCall (Backends.lowerExprNative - (.call "mstore" [.lit 0, .call "sload" [.lit 0]])), - .ExprStmtCall (Backends.lowerExprNative - (.call "return" [.lit 0, .lit 32]))] +/-- Supported constructors already carry the effect-surface closure witness in +their `SupportedConstructor` body interface. The only remaining explicit +premise here is the stronger state-surface closure, because constructor support +currently stores the weaker except-mapping-writes state interface. -/ +theorem generatedConstructorSafeBody_of_supported_state_closed' + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) : + ∀ ctor, spec.constructor = some ctor → + stmtListTouchesUnsupportedStateSurface ctor.body = false → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .memory [] false ctor.body := by + intro ctor hctor hState + exact generatedConstructorSafeBody_of_supported_state_closed + hSupported ctor hctor hState + (hSupported.constructor ctor hctor).body.effects.surfaceClosed -/-- 2-statement lt-calldatasize-stripped tail of -`simpleStorageLoweredRetrieveCaseBodyTail2`, with both the callvalue revert -guard and the inner `if lt(calldatasize, 4) {…}` argument-length revert -guard removed. Used to further shrink the dispatcher hit-case body-exec -obligation when the calldata is at least 4 bytes (which is automatic for any -ABI-conforming call since the selector itself is 4 bytes). -/ -def simpleStorageLoweredRetrieveCaseBodyTail3 : List EvmYul.Yul.Ast.Stmt := - [.ExprStmtCall (Backends.lowerExprNative - (.call "mstore" [.lit 0, .call "sload" [.lit 0]])), - .ExprStmtCall (Backends.lowerExprNative - (.call "return" [.lit 0, .lit 32]))] +/-- Supported constructor bodies compile under the memory dynamic-data source. +For constructors whose supported interface uses the weaker mapping-write state +surface, a per-statement slot-safety witness is enough to obtain the native +safe-body package without requiring the stronger full state-surface premise. -/ +theorem generatedConstructorSafeBody_of_supported_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) : + ∀ ctor, spec.constructor = some ctor → + (∀ stmt, stmt ∈ ctor.body → StmtMappingWriteSlotSafe spec.fields stmt) → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .memory [] false ctor.body := by + intro ctor hctor hSafety + exact supportedStmtList_safe_of_state_except_mapping_writes_stmt_safety + (dynamicSource := .memory) + (generatedConstructorSupportedStmtList_of_supported hSupported ctor hctor) + hSafety + (hSupported.constructor ctor hctor).body.state.surfaceClosed + (hSupported.constructor ctor hctor).body.effects.surfaceClosed -/-- Strip the leading `if callvalue() { revert(0,0) }` guard from -`simpleStorageLoweredStoreCaseBodyTail` when proving a `.error err` -obligation, given that the current `executionEnv.weiValue` is zero (the -canonical zero literal). Combines the harness skip lemma -`exec_if_lowerExprNative_callvalue_skip_zero_fuel` (the callvalue guard -is a no-op at zero `weiValue`) with `exec_block_cons_tail_error` (a -successful head followed by an erroring tail makes the whole block -error). Reduces a 5-statement tail obligation to a 4-statement -callvalue-stripped tail2 obligation. -/ -theorem exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error - (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (err : EvmYul.Yul.Exception) - (hWei : shared.executionEnv.weiValue = (⟨0⟩ : EvmYul.Literal)) - (hTail2 : - EvmYul.Yul.exec (fuel + 7) (.Block simpleStorageLoweredStoreCaseBodyTail2) - codeOverride (.Ok shared store) = .error err) : - EvmYul.Yul.exec (fuel + 8) (.Block simpleStorageLoweredStoreCaseBodyTail) - codeOverride (.Ok shared store) = .error err := by - show EvmYul.Yul.exec (Nat.succ (fuel + 7)) - (.Block ((simpleStorageLoweredStoreCaseBodyTail).head! :: - simpleStorageLoweredStoreCaseBodyTail2)) - codeOverride (.Ok shared store) = .error err - refine Backends.Native.exec_block_cons_tail_error (fuel + 7) _ - simpleStorageLoweredStoreCaseBodyTail2 codeOverride - (.Ok shared store) (.Ok shared store) err ?_ hTail2 - show EvmYul.Yul.exec ((fuel + 1) + 6) - (.If (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) - [.ExprStmtCall (Backends.lowerExprNative - (.call "revert" [.lit 0, .lit 0]))]) - codeOverride (.Ok shared store) = .ok (.Ok shared store) - exact Backends.Native.exec_if_lowerExprNative_callvalue_skip_zero_fuel - (fuel + 1) _ codeOverride shared store hWei +/-- If a constructor body has a `BridgedSafeStmts` witness, the Yul statements +produced for the user-written constructor body are bridged. This intentionally +talks about the compiled body chunk, not `genConstructorArgLoads`, whose +initcode-only builtins are tracked separately. -/ +theorem compileConstructorBody_bridged_of_safe + (fields : List CompilationModel.Field) + (events : List CompilationModel.EventDef) + (errors : List CompilationModel.ErrorDef) + (ctor : CompilationModel.ConstructorSpec) + (bodyStmts : List Yul.YulStmt) + (hSafe : + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + fields errors .memory [] false ctor.body) + (hBody : + CompilationModel.compileStmtList fields events errors .memory [] false + (ctor.params.map (·.name)) [] ctor.body = .ok bodyStmts) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts bodyStmts := by + exact Compiler.Proofs.YulGeneration.Backends.compileStmtList_always_bridged + fields events errors .memory [] false ctor.body (ctor.params.map (·.name)) + hSafe hBody -/-- Retrieve-case dual of -`exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error`. -/ -theorem exec_block_simpleStorageLoweredRetrieveCaseBodyTail_callvalue_strip_error - (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (err : EvmYul.Yul.Exception) - (hWei : shared.executionEnv.weiValue = (⟨0⟩ : EvmYul.Literal)) - (hTail2 : - EvmYul.Yul.exec (fuel + 6) - (.Block simpleStorageLoweredRetrieveCaseBodyTail2) - codeOverride (.Ok shared store) = .error err) : - EvmYul.Yul.exec (fuel + 7) (.Block simpleStorageLoweredRetrieveCaseBodyTail) - codeOverride (.Ok shared store) = .error err := by - show EvmYul.Yul.exec (Nat.succ (fuel + 6)) - (.Block ((simpleStorageLoweredRetrieveCaseBodyTail).head! :: - simpleStorageLoweredRetrieveCaseBodyTail2)) - codeOverride (.Ok shared store) = .error err - refine Backends.Native.exec_block_cons_tail_error (fuel + 6) _ - simpleStorageLoweredRetrieveCaseBodyTail2 codeOverride - (.Ok shared store) (.Ok shared store) err ?_ hTail2 - show EvmYul.Yul.exec ((fuel) + 6) - (.If (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) - [.ExprStmtCall (Backends.lowerExprNative - (.call "revert" [.lit 0, .lit 0]))]) - codeOverride (.Ok shared store) = .ok (.Ok shared store) - exact Backends.Native.exec_if_lowerExprNative_callvalue_skip_zero_fuel - fuel _ codeOverride shared store hWei +/-- Supported constructor user bodies compile to `BridgedStmts` once the +stronger constructor state-surface closure is available. The effect closure is +pulled from `SupportedSpec`; this still excludes the initcode-only argument +copy wrapper. -/ +theorem compileConstructorBody_bridged_of_supported_state_closed + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) + (ctor : CompilationModel.ConstructorSpec) + (bodyStmts : List Yul.YulStmt) + (hctor : spec.constructor = some ctor) + (hState : stmtListTouchesUnsupportedStateSurface ctor.body = false) + (hBody : + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .memory [] false (ctor.params.map (·.name)) [] ctor.body = + .ok bodyStmts) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts bodyStmts := by + exact compileConstructorBody_bridged_of_safe spec.fields spec.events + spec.errors ctor bodyStmts + (generatedConstructorSafeBody_of_supported_state_closed' + hSupported ctor hctor hState) + hBody -/-- Strip the leading `if lt(calldatasize(), 4) { revert(0,0) }` argument-length -guard from `simpleStorageLoweredRetrieveCaseBodyTail2` when proving a -`.error err` obligation, given that the current calldata has at least 4 -bytes (the selector). Combines the harness skip lemma -`exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel` with -`exec_block_cons_tail_error`. Reduces a 3-statement tail2 obligation to a -2-statement lt-stripped tail3 obligation. -/ -theorem exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error - (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (err : EvmYul.Yul.Exception) - (hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size) - (hGe : 4 ≤ shared.executionEnv.calldata.size) - (hTail3 : - EvmYul.Yul.exec (fuel + 9) - (.Block simpleStorageLoweredRetrieveCaseBodyTail3) - codeOverride (.Ok shared store) = .error err) : - EvmYul.Yul.exec (fuel + 10) - (.Block simpleStorageLoweredRetrieveCaseBodyTail2) - codeOverride (.Ok shared store) = .error err := by - show EvmYul.Yul.exec (Nat.succ (fuel + 9)) - (.Block ((simpleStorageLoweredRetrieveCaseBodyTail2).head! :: - simpleStorageLoweredRetrieveCaseBodyTail3)) - codeOverride (.Ok shared store) = .error err - refine Backends.Native.exec_block_cons_tail_error (fuel + 9) _ - simpleStorageLoweredRetrieveCaseBodyTail3 codeOverride - (.Ok shared store) (.Ok shared store) err ?_ hTail3 - show EvmYul.Yul.exec (fuel + 9) - (.If (Backends.lowerExprNative - (Yul.YulExpr.call "lt" - [Yul.YulExpr.call "calldatasize" [], - Yul.YulExpr.lit 4])) - [.ExprStmtCall (Backends.lowerExprNative - (.call "revert" [.lit 0, .lit 0]))]) - codeOverride (.Ok shared store) = .ok (.Ok shared store) - exact Backends.Native.exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel - fuel _ codeOverride shared store 4 hSize (by decide) hGe +/-- Supported constructor user bodies compile to `BridgedStmts` under the +weaker mapping-write state surface when the body-local mapping-write +slot-safety witness is supplied. -/ +theorem compileConstructorBody_bridged_of_supported_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) + (ctor : CompilationModel.ConstructorSpec) + (bodyStmts : List Yul.YulStmt) + (hctor : spec.constructor = some ctor) + (hSafety : + ∀ stmt, stmt ∈ ctor.body → StmtMappingWriteSlotSafe spec.fields stmt) + (hBody : + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .memory [] false (ctor.params.map (·.name)) [] ctor.body = + .ok bodyStmts) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts bodyStmts := by + exact compileConstructorBody_bridged_of_safe spec.fields spec.events + spec.errors ctor bodyStmts + (generatedConstructorSafeBody_of_supported_stmt_safety + hSupported ctor hctor hSafety) + hBody -/-- Store-case dual of -`exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error`, with -the ABI argument guard threshold `36 = 4 + 32`. -/ -theorem exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error - (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (err : EvmYul.Yul.Exception) - (hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size) - (hGe : 36 ≤ shared.executionEnv.calldata.size) - (hTail3 : - EvmYul.Yul.exec (fuel + 10) - (.Block simpleStorageLoweredStoreCaseBodyTail3) - codeOverride (.Ok shared store) = .error err) : - EvmYul.Yul.exec (fuel + 11) - (.Block simpleStorageLoweredStoreCaseBodyTail2) - codeOverride (.Ok shared store) = .error err := by - show EvmYul.Yul.exec (Nat.succ (fuel + 10)) - (.Block ((simpleStorageLoweredStoreCaseBodyTail2).head! :: - simpleStorageLoweredStoreCaseBodyTail3)) - codeOverride (.Ok shared store) = .error err - refine Backends.Native.exec_block_cons_tail_error (fuel + 10) _ - simpleStorageLoweredStoreCaseBodyTail3 codeOverride - (.Ok shared store) (.Ok shared store) err ?_ hTail3 - show EvmYul.Yul.exec (fuel + 10) - (.If (Backends.lowerExprNative - (Yul.YulExpr.call "lt" - [Yul.YulExpr.call "calldatasize" [], - Yul.YulExpr.lit 36])) - [.ExprStmtCall (Backends.lowerExprNative - (.call "revert" [.lit 0, .lit 0]))]) - codeOverride (.Ok shared store) = .ok (.Ok shared store) - exact Backends.Native.exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel - (fuel + 1) _ codeOverride shared store 36 hSize (by decide) hGe +/-- Under `SupportedSpec`, successful compilation records the deploy field as +the output of `compileConstructor`. -/ +theorem generatedDeploy_compileConstructor_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + CompilationModel.compileConstructor spec.fields spec.events spec.errors [] + spec.constructor = .ok irContract.deploy := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_deploy_compileConstructor + spec selectors hSupported irContract hCompile -/-- Store-case argument-length guard fires when calldata contains only the -selector. This is the short-calldata counterpart to -`exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error`. -/ -theorem exec_block_simpleStorageLoweredStoreCaseBodyTail2_short_revert - (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hSizeEq : shared.executionEnv.calldata.size = 4) : - EvmYul.Yul.exec (fuel + 11) - (.Block simpleStorageLoweredStoreCaseBodyTail2) - codeOverride (.Ok shared store) = - .error EvmYul.Yul.Exception.Revert := by - show EvmYul.Yul.exec (Nat.succ (fuel + 10)) - (.Block ((simpleStorageLoweredStoreCaseBodyTail2).head! :: - simpleStorageLoweredStoreCaseBodyTail3)) - codeOverride (.Ok shared store) = .error EvmYul.Yul.Exception.Revert - refine Backends.Native.exec_block_cons_error (fuel + 10) _ - simpleStorageLoweredStoreCaseBodyTail3 codeOverride - (.Ok shared store) EvmYul.Yul.Exception.Revert ?_ - refine Backends.Native.exec_if_eval_nonzero_error (fuel + 9) _ _ - codeOverride (.Ok shared store) (.Ok shared store) - (EvmYul.UInt256.ofNat 1) EvmYul.Yul.Exception.Revert ?_ ?_ ?_ - · rw [Backends.Native.eval_lowerExprNative_lt_calldatasize_ok_fuel] - simp [hSizeEq, EvmYul.UInt256.lt, EvmYul.UInt256.ofNat, Fin.ofNat, - EvmYul.UInt256.size] - decide - · change (EvmYul.UInt256.ofNat 1 : EvmYul.UInt256) ≠ ⟨0⟩ - decide - · simpa [Backends.Native.nativeRevertZeroZeroStmt, Backends.lowerExprNative, - Backends.lookupRuntimePrimOp] using - (Backends.Native.exec_block_cons_error (fuel + 8) - Backends.Native.nativeRevertZeroZeroStmt [] codeOverride - (.Ok shared store) EvmYul.Yul.Exception.Revert - (Backends.Native.exec_revert_zero_zero_error (fuel + 2) - (.Ok shared store) codeOverride)) +private theorem generatedRuntimePrefixFunctionNamesUnique_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique + ((if irContract.usesMapping then [Compiler.mappingSlotFuncAt 0] else []) ++ + irContract.internalFunctions) = true := by + have hInternalNil : irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hInternalNil] + by_cases hUsesMapping : irContract.usesMapping + · simp [hUsesMapping, + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique, + Compiler.Proofs.YulGeneration.Backends.Native.stringListHasDuplicate, + Compiler.mappingSlotFuncAt, Compiler.CodegenCommon.mappingSlotFuncAt] + · simp [hUsesMapping, + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique, + Compiler.Proofs.YulGeneration.Backends.Native.stringListHasDuplicate] -/-- Closed-form native exec of the store hit-case 3-statement payload - `let value := calldataload(4); sstore(0, value); stop` after the - callvalue and argument-length guards have been stripped. -/ -theorem exec_block_simpleStorageLoweredStoreCaseBodyTail3_halt - (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) - (arg : Nat) (rest : List Nat) (hArgs : tx.args = arg :: rest) : - let initialWithStore : EvmYul.Yul.State := - .Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState store - let withValue := initialWithStore.insert "value" - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) - let finalState := withValue.setState - (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) - EvmYul.Yul.exec (fuel + 10) - (.Block simpleStorageLoweredStoreCaseBodyTail3) - codeOverride initialWithStore = - .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by - intro initialWithStore withValue finalState - have hWord : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.calldataload (EvmYul.UInt256.ofNat 4) = - Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg := by - simpa [EvmYul.Yul.State.toState] using - Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataload4_arg0_word - Compiler.SimpleStorageNativeWitness.nativeContract tx storage observableSlots - arg rest hArgs - simp [simpleStorageLoweredStoreCaseBodyTail3, Backends.lowerExprNative, - Backends.lookupRuntimePrimOp, EvmYul.Yul.exec, EvmYul.Yul.eval, - EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, EvmYul.Yul.execPrimCall, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', - EvmYul.Yul.State.multifill, initialWithStore, withValue, finalState, - hWord, EvmYul.Yul.State.insert, GetElem?.getElem!, decidableGetElem?, - GetElem.getElem, EvmYul.Yul.State.store, EvmYul.Yul.State.lookup!] - have hPerm : - (EvmYul.Yul.State.Ok - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState - (Finmap.insert "value" - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) - store)).executionEnv.perm = true := by - rfl - rw [show fuel + 7 = (fuel + 6) + 1 by omega] - rw [Compiler.Proofs.YulGeneration.Backends.Native.primCall_sstore_ok - (fuel + 6) _ _ _ hPerm] - rfl +private theorem generatedRuntimePrefixFunctionNamesUnique_of_compile_ok_supported_except_mapping_writes + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) : + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique + ((if irContract.usesMapping then [Compiler.mappingSlotFuncAt 0] else []) ++ + irContract.internalFunctions) = true := by + have hInternalNil : irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_internalFunctions_nil_except_mapping_writes + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hInternalNil] + by_cases hUsesMapping : irContract.usesMapping + · simp [hUsesMapping, + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique, + Compiler.Proofs.YulGeneration.Backends.Native.stringListHasDuplicate, + Compiler.mappingSlotFuncAt, Compiler.CodegenCommon.mappingSlotFuncAt] + · simp [hUsesMapping, + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique, + Compiler.Proofs.YulGeneration.Backends.Native.stringListHasDuplicate] -/-- Composed body-level closed form for the SimpleStorage store hit-case when -the calldata contains the setter argument. -/ -theorem exec_block_simpleStorageLoweredStoreCaseBody_halt - (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) - (arg : Nat) (rest : List Nat) (hArgs : tx.args = arg :: rest) - (hWei : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.weiValue = - (⟨0⟩ : EvmYul.Literal)) - (hSize : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.calldata.size < - EvmYul.UInt256.size) - (hGe : - 36 ≤ (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.calldata.size) : - let initialWithStore : EvmYul.Yul.State := - .Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState store - let withValue := initialWithStore.insert "value" - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) - let finalState := withValue.setState - (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) - EvmYul.Yul.exec (fuel + 13) (.Block simpleStorageLoweredStoreCaseBody) - codeOverride initialWithStore = - .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by - intro initialWithStore withValue finalState - have hTail3 := exec_block_simpleStorageLoweredStoreCaseBodyTail3_halt - fuel codeOverride tx storage observableSlots store arg rest hArgs - have hTail2 := exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error - fuel codeOverride - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState - store _ hSize hGe hTail3 - have hTail := exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error - (fuel + 4) codeOverride - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState - store _ hWei hTail2 - exact exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error - (fuel + 11) codeOverride initialWithStore _ hTail +/-- Supported compiler output has no emitted internal helper statements. This +discharges the generated-runtime fragment's internal-function-shape witness. -/ +private theorem generatedRuntimeInternalsAreFuncDefs_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + ∀ stmt, stmt ∈ irContract.internalFunctions → + ∃ name params rets body, stmt = Yul.YulStmt.funcDef name params rets body := by + intro stmt hmem + have hInternalNil : irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hInternalNil] at hmem + simp at hmem -/-- Closed-form native exec of the retrieve hit-case 2-statement payload - `mstore(0, sload(0)) ; return(0, 32)`. EVMYulLean models `RETURN` as a - halt error; the exec composes the harness's exec-side - `mstore(lit, sload(lit))` seam with the exec-side `return(lit, lit)` - halt seam through `exec_block_cons_tail_error`. The resulting halt state - threads (i) storage-access tracking from the SLOAD on slot zero, - (ii) the memory write of the loaded word at offset zero, and - (iii) the post-`evmReturn` machine state holding the 32-byte return - buffer. Discharges the `hTail3` premise of - `exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error` - unconditionally — no extra calldata/wei hypotheses needed because the - payload reads only from storage and writes only to memory. -/ -theorem exec_block_simpleStorageLoweredRetrieveCaseBodyTail3_closed - (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) : - EvmYul.Yul.exec (fuel + 9) - (.Block simpleStorageLoweredRetrieveCaseBodyTail3) - codeOverride (.Ok shared store) = - let (state', value) := shared.sload (EvmYul.UInt256.ofNat 0) - let shared1 : EvmYul.SharedState .Yul := { shared with toState := state' } - let shared2 : EvmYul.SharedState .Yul := - { shared1 with - toMachineState := - shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } - let shared3 : EvmYul.SharedState .Yul := - { shared2 with - toMachineState := - shared2.toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } - .error (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store) ⟨1⟩) := by - show EvmYul.Yul.exec (Nat.succ (fuel + 8)) - (.Block ((simpleStorageLoweredRetrieveCaseBodyTail3).head! :: - [(simpleStorageLoweredRetrieveCaseBodyTail3).getLast!])) - codeOverride (.Ok shared store) = _ - refine Backends.Native.exec_block_cons_tail_error (fuel + 8) _ _ codeOverride - (.Ok shared store) _ _ - (Backends.Native.exec_lowerExprNative_mstore_lit_sload_lit_ok_fuel - fuel shared store codeOverride 0 0) ?_ - -- Tail [return(0, 32)] errors via the singleton-return harness lemma. - have hSeam := - Backends.Native.exec_block_singleton_lowerExprNative_return_lit_lit_error_fuel - (fuel + 1) - ({ ({ shared with toState := (shared.sload (EvmYul.UInt256.ofNat 0)).1 } - : EvmYul.SharedState .Yul) with - toMachineState := - ({ shared with toState := (shared.sload (EvmYul.UInt256.ofNat 0)).1 } - : EvmYul.SharedState .Yul).toMachineState.mstore - (EvmYul.UInt256.ofNat 0) (shared.sload (EvmYul.UInt256.ofNat 0)).2 }) - store codeOverride 0 32 - have hF : (fuel + 1) + 7 = fuel + 8 := by omega - rw [hF] at hSeam - simpa [simpleStorageLoweredRetrieveCaseBodyTail3] using hSeam +private theorem generatedRuntimeInternalsAreFuncDefs_of_compile_ok_supported_except_mapping_writes + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) : + ∀ stmt, stmt ∈ irContract.internalFunctions → + ∃ name params rets body, stmt = Yul.YulStmt.funcDef name params rets body := by + intro stmt hmem + have hInternalNil : irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_internalFunctions_nil_except_mapping_writes + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hInternalNil] at hmem + simp at hmem -/-- Composed body-level closed form for the SimpleStorage retrieve hit-case. -Stacks the three guard-strip lemmas (head no-op, callvalue, lt-calldatasize) -on top of `_Tail3_closed` to characterize the full lowered retrieve body's -exec output as the closed-form halt error produced by -`mstore(0, sload(0)); return(0, 32)`. The `shared3` form mirrors `_Tail3_closed`. -/ -theorem exec_block_simpleStorageLoweredRetrieveCaseBody_halt - (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hWei : shared.executionEnv.weiValue = (⟨0⟩ : EvmYul.Literal)) - (hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size) - (hGe : 4 ≤ shared.executionEnv.calldata.size) : - EvmYul.Yul.exec (fuel + 12) (.Block simpleStorageLoweredRetrieveCaseBody) - codeOverride (.Ok shared store) = - let (state', value) := shared.sload (EvmYul.UInt256.ofNat 0) - let shared1 : EvmYul.SharedState .Yul := { shared with toState := state' } - let shared2 : EvmYul.SharedState .Yul := - { shared1 with - toMachineState := - shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } - let shared3 : EvmYul.SharedState .Yul := - { shared2 with - toMachineState := - shared2.toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } - .error (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store) ⟨1⟩) := by - have hTail3 := exec_block_simpleStorageLoweredRetrieveCaseBodyTail3_closed - fuel codeOverride shared store - have hTail2 := exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error - fuel codeOverride shared store _ hSize hGe hTail3 - have hTail := exec_block_simpleStorageLoweredRetrieveCaseBodyTail_callvalue_strip_error - (fuel + 4) codeOverride shared store _ hWei hTail2 - exact exec_block_simpleStorageLoweredRetrieveCaseBody_head_strip_error - (fuel + 10) codeOverride (.Ok shared store) _ hTail +/-- Every emitted external function body in supported compiler output is in the +native bridgeable Yul subset. -/ +theorem generatedRuntimeExternalBodiesBridged_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body := + compiledExternalFunctions_bridged_of_safe_static + spec.fields spec.events spec.errors + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_compiled_functions + spec selectors hSupported irContract hCompile) + (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) -/-- Concrete characterization of the lowered SimpleStorage source switch -cases. Both bodies are straight-line, so the lowering is deterministic and -the threaded `nextSwitchId` returns unchanged. Strengthens `_lowered_shape` -from a two-element shape with unspecified bodies to a fixed shape with -explicit lowered bodies, anchoring downstream hit-case proofs against the -harness primitive-call lemmas. -/ -theorem simpleStorageBuildSwitchSourceCases_lowered_concrete - (reservedNames : List String) (nextSwitchId : Nat) : - Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames nextSwitchId - simpleStorageBuildSwitchSourceCases = - .ok ([(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)], - nextSwitchId) := by - simp only [simpleStorageLoweredStoreCaseBody, - simpleStorageLoweredRetrieveCaseBody, - simpleStorageBuildSwitchSourceCases, simpleStorageIRContract, - Compiler.CodegenCommon.dispatchBody, - Compiler.CodegenCommon.callvalueGuard, - Compiler.CodegenCommon.calldatasizeGuard, - List.map_cons, List.map_nil, List.append_nil, - List.cons_append, List.nil_append, List.length_cons, List.length_nil, - if_false, Bool.false_eq_true, - Backends.lowerSwitchCasesNativeWithSwitchIds_cons, - Backends.lowerSwitchCasesNativeWithSwitchIds_nil, - Backends.lowerStmtsNativeWithSwitchIds_cons, - Backends.lowerStmtsNativeWithSwitchIds_nil, - Backends.lowerStmtGroupNativeWithSwitchIds_comment, - Backends.lowerStmtGroupNativeWithSwitchIds_let, - Backends.lowerStmtGroupNativeWithSwitchIds_expr, - Backends.lowerStmtGroupNativeWithSwitchIds_if, - Bind.bind, Except.bind, pure, Except.pure] +/-- Every emitted external function body in the weaker mapping-write-supported +compiler output is in the native bridgeable Yul subset once each actual +mapping-write statement carries slot-safety evidence. -/ +theorem generatedRuntimeExternalBodiesBridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body := + compiledExternalFunctions_bridged_of_safe_static + spec.fields spec.events spec.errors + (Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions_except_mapping_writes + spec selectors hSupported irContract hCompile) + (generatedRuntimeStaticScalarParams_of_supported_except_mapping_writes + hSupported) + (generatedRuntimeSafeBodies_of_supported_except_mapping_writes_stmt_safety + hSupported hSafety) -/-- Closed-form selector-miss bridge endpoint for SimpleStorage native -dispatcher. Takes only source-level selector facts (`selector ≠ 0x6057361d` -and `selector ≠ 0x2e64cec1`, the two SimpleStorage IR selectors) and -produces the dispatcher exec result `.error Revert` at fuel `fuel + 21` -(`= fuel + cases'.length + 19` with `cases'.length = 2`). The proof opens the -`_sourceLowered` existential, derives `cases'.find? = none` and `tags-range` -from the source-cases facts via `_find?_none` / `_tags_eq` chained with -`simpleStorageBuildSwitchSourceCases_find?_none` and `_tags_lt_uint256_size`, -then composes through `_selectorMiss_revert_via_reduction`. This lifts the -remaining selector-miss obligation in the SimpleStorage native dispatcher -bridge to a purely source-level statement. -/ -theorem simpleStorageNativeContract_dispatcherExec_selectorMiss_revert - (fuel selector : Nat) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hSelMissStore : selector ≠ 0x6057361d) - (hSelMissRetrieve : selector ≠ 0x2e64cec1) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + 21) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = - .error EvmYul.Yul.Exception.Revert := by - obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := - simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - (fuel + 7) tx storage observableSlots hNoWrap - have hLen : cases'.length = 2 := by - have h := Backends.lowerSwitchCasesNativeWithSwitchIds_length_eq - _ _ _ _ _ hLowerCases - rw [h]; rfl - have hFind : cases'.find? (fun entry => entry.1 == selector) = none := - Backends.lowerSwitchCasesNativeWithSwitchIds_find?_none - _ _ _ _ _ _ hLowerCases - (simpleStorageBuildSwitchSourceCases_find?_none hSelMissStore hSelMissRetrieve) - have hTags := Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq - _ _ _ _ _ hLowerCases - have hTagsRange : ∀ tag body, (tag, body) ∈ cases' → - tag < EvmYul.UInt256.size := by - intro tag body hMem - have hMemTag : tag ∈ cases'.map (·.1) := List.mem_map_of_mem hMem - rw [hTags, simpleStorageBuildSwitchSourceCases_map_fst] at hMemTag - simp only [List.mem_cons, List.not_mem_nil, or_false] at hMemTag - rcases hMemTag with rfl | rfl <;> decide - have hReduction := hExec - rw [show (fuel + 7 + 14 : Nat) = fuel + cases'.length + 19 by rw [hLen], - show (fuel + 7 + 8 : Nat) = fuel + cases'.length + 13 by rw [hLen]] - at hReduction - have h := simpleStorageNativeContract_dispatcherExec_selectorMiss_revert_via_reduction - fuel selector (Backends.freshNativeSwitchId reservedNames n0) cases' - tx storage observableSlots hSelector hSelectorRange hFind hTagsRange - hReduction - rw [show fuel + cases'.length + 19 = fuel + 21 by rw [hLen]] at h - exact h +/-- Supported compiler output currently emits no fallback entrypoint, so the +fallback-body bridge obligation consumed by the generic runtime-code bridge is +vacuously discharged. Keeping this as a named theorem makes the +fallback/receive branch of `emitYul` explicit at the end-to-end layer. -/ +theorem generatedRuntimeFallbackBodyBridged_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + ∀ fb, irContract.fallbackEntrypoint = some fb → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fb.body := by + intro fb hfb + have hNoFallback : + irContract.fallbackEntrypoint = none := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile + rw [hNoFallback] at hfb + simp at hfb -/-- Post-`__has_selector := 1` switch-prefix state at a hit, with the matched -flag set: the input state shape consumed by the selected body inside the -lowered native switch's hit branch. -/ -def simpleStorageDispatcherHitBodyInputState - (switchId : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) : EvmYul.Yul.State := - ((((.Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots).sharedState - ((∅ : EvmYul.Yul.VarStore).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)) : EvmYul.Yul.State).insert - (Backends.nativeSwitchDiscrTempName switchId) - (EvmYul.UInt256.ofNat - (tx.functionSelector % Compiler.Constants.selectorModulus))).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 0)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1)) +/-- Supported compiler output currently emits no receive entrypoint, so the +receive-body bridge obligation consumed by the generic runtime-code bridge is +vacuously discharged. -/ +theorem generatedRuntimeReceiveBodyBridged_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + ∀ rc, irContract.receiveEntrypoint = some rc → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts rc.body := by + intro rc hrc + have hNoReceive : + irContract.receiveEntrypoint = none := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile + rw [hNoReceive] at hrc + simp at hrc -/-- Hit-case dual of `_selectorMiss_revert_via_reduction` for the -SimpleStorage `store(uint256)` selector: composes the harness-level -`exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error` -with the strengthened-reduction equation, parametric in `cases'`, the lowered -bodies, and the body-execution `err`. -/ -theorem simpleStorageNativeContract_dispatcherExec_storeHit_error_via_reduction - (fuel switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (err : EvmYul.Yul.Exception) - (hSelector : - 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) - (hCases : cases' = [(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')]) - (hBody : ∀ pre suffix, cases' = pre ++ (0x6057361d, storeBody') :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block storeBody') - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState switchId tx storage - observableSlots) = .error err) - (hReduction : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + cases'.length + 19) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = - EvmYul.Yul.exec (fuel + cases'.length + 13) - (.Block [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' [Backends.Native.nativeRevertZeroZeroStmt]]) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots).insert "__has_selector" - (EvmYul.UInt256.ofNat 1))) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + cases'.length + 19) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = .error err := by - rw [hReduction] - refine Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error - fuel 0x6057361d switchId 0x6057361d cases' - [Backends.Native.nativeRevertZeroZeroStmt] storeBody' - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots err hSelector ?_ ?_ ?_ ?_ - · rw [hCases]; rfl - · norm_num [EvmYul.UInt256.size] - · intro tag body hMem; rw [hCases] at hMem - simp only [List.mem_cons, Prod.mk.injEq, List.not_mem_nil, or_false] at hMem - rcases hMem with ⟨rfl, _⟩ | ⟨rfl, _⟩ <;> decide - · simpa [simpleStorageDispatcherHitBodyInputState] using hBody +/-- The weaker mapping-write-supported compiler output also emits no fallback +entrypoint, so the fallback-body bridge obligation is vacuous there too. -/ +theorem generatedRuntimeFallbackBodyBridged_of_compile_ok_supported_except_mapping_writes + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) : + ∀ fb, irContract.fallbackEntrypoint = some fb → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fb.body := by + intro fb hfb + have hNoFallback : + irContract.fallbackEntrypoint = none := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_noFallbackEntrypoint_except_mapping_writes + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hNoFallback] at hfb + simp at hfb -def simpleStorageLoweredHitCasesShape - (reservedNames : List String) (n0 midN : Nat) - (storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt) : Prop := - Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames - (Backends.freshNativeSwitchId reservedNames n0 + 1) - simpleStorageBuildSwitchSourceCases = - .ok ([(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')], midN) +/-- The weaker mapping-write-supported compiler output also emits no receive +entrypoint, so the receive-body bridge obligation is vacuous there too. -/ +theorem generatedRuntimeReceiveBodyBridged_of_compile_ok_supported_except_mapping_writes + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) : + ∀ rc, irContract.receiveEntrypoint = some rc → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts rc.body := by + intro rc hrc + have hNoReceive : + irContract.receiveEntrypoint = none := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_noReceiveEntrypoint_except_mapping_writes + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hNoReceive] at hrc + simp at hrc -theorem simpleStorageNativeContract_dispatcherExec_storeHit_error - (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (err : EvmYul.Yul.Exception) - (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hBody : ∀ (reservedNames : List String) (n0 midN : Nat) - (storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt), - simpleStorageLoweredHitCasesShape reservedNames n0 midN storeBody' retrieveBody' → - EvmYul.Yul.exec (fuel + 9) (.Block storeBody') - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState - (Backends.freshNativeSwitchId reservedNames n0) tx storage observableSlots) = - .error err) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage observableSlots) = - .error err := by - obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := - simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - (fuel + 7) tx storage observableSlots hNoWrap - obtain ⟨storeBody', retrieveBody', hCases⟩ := - simpleStorageBuildSwitchSourceCases_lowered_shape reservedNames _ midN cases' hLowerCases - subst hCases - have hBody' := hBody reservedNames n0 midN storeBody' retrieveBody' hLowerCases - have hReduction := hExec - rw [show (fuel + 7 + 14 : Nat) = fuel + 2 + 19 from by omega, - show (fuel + 7 + 8 : Nat) = fuel + 2 + 13 from by omega, - show (2 : Nat) = ([(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] : - List (Nat × List EvmYul.Yul.Ast.Stmt)).length from rfl] at hReduction - have h := simpleStorageNativeContract_dispatcherExec_storeHit_error_via_reduction - fuel (Backends.freshNativeSwitchId reservedNames n0) - [(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] - storeBody' retrieveBody' tx storage observableSlots err - hSelector rfl ?_ hReduction - · rw [show fuel + ([(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] : - List (Nat × List EvmYul.Yul.Ast.Stmt)).length + 19 = fuel + 21 from rfl] at h - exact h - · rintro (_ | ⟨⟨_, _⟩, rest⟩) suffix hDecomp - · simp only [List.nil_append, List.cons.injEq] at hDecomp - obtain ⟨_, hSuf⟩ := hDecomp; subst hSuf; simpa using hBody' - · exfalso - simp only [List.cons_append, List.cons.injEq] at hDecomp - obtain ⟨_, hRest⟩ := hDecomp - cases rest with - | nil => simp only [List.nil_append, List.cons.injEq, Prod.mk.injEq] at hRest - exact absurd hRest.1.1 (by decide) - | cons _ _ => simp at hRest +private theorem bridgedExpr_dispatch_callvalue : + BridgedExpr (Compiler.Yul.YulExpr.call "callvalue" []) := by + exact BridgedExpr.call "callvalue" [] (Or.inl (by simp [bridgedBuiltins])) + (by intro arg hMem; cases hMem) -theorem simpleStorageLoweredHitCasesShape_concrete - {reservedNames : List String} {n0 midN : Nat} - {storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt} - (hShape : simpleStorageLoweredHitCasesShape reservedNames n0 midN - storeBody' retrieveBody') : - storeBody' = simpleStorageLoweredStoreCaseBody ∧ - retrieveBody' = simpleStorageLoweredRetrieveCaseBody := by - have hC := simpleStorageBuildSwitchSourceCases_lowered_concrete - reservedNames (Backends.freshNativeSwitchId reservedNames n0 + 1) - unfold simpleStorageLoweredHitCasesShape at hShape - rw [hC] at hShape - simp only [Except.ok.injEq, Prod.mk.injEq, List.cons.injEq] at hShape - exact ⟨hShape.1.1.2.symm, hShape.1.2.1.2.symm⟩ +private theorem bridgedExpr_dispatch_calldatasize : + BridgedExpr (Compiler.Yul.YulExpr.call "calldatasize" []) := by + exact BridgedExpr.call "calldatasize" [] (Or.inl (by simp [bridgedBuiltins])) + (by intro arg hMem; cases hMem) -/-- Concrete-body variant of `_dispatcherExec_storeHit_error`. The caller now -only has to discharge the body-exec obligation on the *fixed* lowered body -`simpleStorageLoweredStoreCaseBody`, instead of universally over any -`storeBody'` that might come out of the lowering. Uses -`simpleStorageLoweredHitCasesShape_concrete` to specialize the underlying -parametric premise. This strictly weakens the hit-case obligation that the -dispatcher bridge proof has to supply. -/ -theorem simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete - (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (err : EvmYul.Yul.Exception) - (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hBody : ∀ (reservedNames : List String) (n0 : Nat), - EvmYul.Yul.exec (fuel + 9) (.Block simpleStorageLoweredStoreCaseBody) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState - (Backends.freshNativeSwitchId reservedNames n0) - tx storage observableSlots) = - .error err) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error err := by - refine simpleStorageNativeContract_dispatcherExec_storeHit_error - fuel tx storage observableSlots err hSelector hNoWrap ?_ - intro reservedNames n0 _ storeBody' _ hShape - obtain ⟨hStore, _⟩ := simpleStorageLoweredHitCasesShape_concrete hShape - rw [hStore] - exact hBody reservedNames n0 +private theorem bridgedExpr_dispatch_selector : + BridgedExpr + (Compiler.Yul.YulExpr.call "shr" + [Compiler.Yul.YulExpr.lit Compiler.Constants.selectorShift, + Compiler.Yul.YulExpr.call "calldataload" [Compiler.Yul.YulExpr.lit 0]]) := by + refine BridgedExpr.call "shr" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_cons, List.mem_nil_iff, or_false] at hMem + rcases hMem with rfl | rfl + · exact BridgedExpr.lit Compiler.Constants.selectorShift + · refine BridgedExpr.call "calldataload" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro inner hInner + simp only [List.mem_singleton] at hInner + subst hInner + exact BridgedExpr.lit 0 -theorem simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete_tail - (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (err : EvmYul.Yul.Exception) - (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hTail : ∀ (reservedNames : List String) (n0 : Nat), - EvmYul.Yul.exec (fuel + 8) (.Block simpleStorageLoweredStoreCaseBodyTail) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState - (Backends.freshNativeSwitchId reservedNames n0) - tx storage observableSlots) = - .error err) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error err := by - refine simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete - fuel tx storage observableSlots err hSelector hNoWrap ?_ - intro reservedNames n0 - exact exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error - (fuel + 7) _ _ err (hTail reservedNames n0) +private theorem bridgedExpr_dispatch_calldatasize_lt (n : Nat) : + BridgedExpr + (Compiler.Yul.YulExpr.call "lt" + [Compiler.Yul.YulExpr.call "calldatasize" [], + Compiler.Yul.YulExpr.lit n]) := by + refine BridgedExpr.call "lt" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_cons, List.mem_nil_iff, or_false] at hMem + rcases hMem with rfl | rfl + · exact bridgedExpr_dispatch_calldatasize + · exact BridgedExpr.lit n -/-- Callvalue-stripped version of `_storeHit_error_concrete_tail`: when the -transaction has zero `msgValue`, the leading `if callvalue() { revert }` guard -is a no-op, so the body-execution premise can be expressed against the -4-statement `simpleStorageLoweredStoreCaseBodyTail2` at fuel `+7` instead of -the 5-statement `simpleStorageLoweredStoreCaseBodyTail` at fuel `+8`. Strictly -shrinks the dispatcher hit-case body-exec obligation under the natural Solidity -assumption that non-payable functions are called with `msg.value = 0`. -/ -theorem simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete_tail2 - (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (err : EvmYul.Yul.Exception) - (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hMsgValue : tx.msgValue = 0) - (hTail2 : ∀ (reservedNames : List String) (n0 : Nat), - EvmYul.Yul.exec (fuel + 7) - (.Block simpleStorageLoweredStoreCaseBodyTail2) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState - (Backends.freshNativeSwitchId reservedNames n0) - tx storage observableSlots) = - .error err) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error err := by - refine simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete_tail - fuel tx storage observableSlots err hSelector hNoWrap ?_ - intro reservedNames n0 - have hWei : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.weiValue = - (⟨0⟩ : EvmYul.Literal) := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_weiValue, - hMsgValue] - rfl - have hT2 := hTail2 reservedNames n0 - show EvmYul.Yul.exec (fuel + 8) (.Block simpleStorageLoweredStoreCaseBodyTail) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (.Ok _ _) = .error err - exact exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error - fuel _ _ _ err hWei hT2 +private theorem bridgedExpr_dispatch_has_selector : + BridgedExpr + (Compiler.Yul.YulExpr.call "iszero" + [Compiler.Yul.YulExpr.call "lt" + [Compiler.Yul.YulExpr.call "calldatasize" [], + Compiler.Yul.YulExpr.lit 4]]) := by + refine BridgedExpr.call "iszero" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_singleton] at hMem + subst hMem + exact bridgedExpr_dispatch_calldatasize_lt 4 -theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error_via_reduction - (fuel switchId : Nat) - (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (err : EvmYul.Yul.Exception) - (hSelector : - 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) - (hCases : cases' = [(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')]) - (hBody : ∀ pre suffix, cases' = pre ++ (0x2e64cec1, retrieveBody') :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block retrieveBody') - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState switchId tx storage - observableSlots) = .error err) - (hReduction : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + cases'.length + 19) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = - EvmYul.Yul.exec (fuel + cases'.length + 13) - (.Block [Backends.lowerNativeSwitchBlock - (Yul.YulExpr.call "shr" [Yul.YulExpr.lit Compiler.Constants.selectorShift, - Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) - switchId cases' [Backends.Native.nativeRevertZeroZeroStmt]]) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots).insert "__has_selector" - (EvmYul.UInt256.ofNat 1))) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + cases'.length + 19) - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots) = .error err := by - rw [hReduction] - refine Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error - fuel 0x2e64cec1 switchId 0x2e64cec1 cases' - [Backends.Native.nativeRevertZeroZeroStmt] retrieveBody' - Compiler.SimpleStorageNativeWitness.nativeContract - tx storage observableSlots err hSelector ?_ ?_ ?_ ?_ - · rw [hCases]; rfl - · norm_num [EvmYul.UInt256.size] - · intro tag body hMem; rw [hCases] at hMem - simp only [List.mem_cons, Prod.mk.injEq, List.not_mem_nil, or_false] at hMem - rcases hMem with ⟨rfl, _⟩ | ⟨rfl, _⟩ <;> decide - · simpa [simpleStorageDispatcherHitBodyInputState] using hBody +private theorem bridgedExpr_dispatch_empty_calldata : + BridgedExpr + (Compiler.Yul.YulExpr.call "eq" + [Compiler.Yul.YulExpr.call "calldatasize" [], + Compiler.Yul.YulExpr.lit 0]) := by + refine BridgedExpr.call "eq" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_cons, List.mem_nil_iff, or_false] at hMem + rcases hMem with rfl | rfl + · exact bridgedExpr_dispatch_calldatasize + · exact BridgedExpr.lit 0 -theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error - (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (err : EvmYul.Yul.Exception) - (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hBody : ∀ (reservedNames : List String) (n0 midN : Nat) - (storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt), - simpleStorageLoweredHitCasesShape reservedNames n0 midN storeBody' retrieveBody' → - EvmYul.Yul.exec (fuel + 8) (.Block retrieveBody') - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState - (Backends.freshNativeSwitchId reservedNames n0) tx storage observableSlots) = - .error err) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage observableSlots) = - .error err := by - obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := - simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - (fuel + 7) tx storage observableSlots hNoWrap - obtain ⟨storeBody', retrieveBody', hCases⟩ := - simpleStorageBuildSwitchSourceCases_lowered_shape reservedNames _ midN cases' hLowerCases - subst hCases - have hBody' := hBody reservedNames n0 midN storeBody' retrieveBody' hLowerCases - have hReduction := hExec - rw [show (fuel + 7 + 14 : Nat) = fuel + 2 + 19 from by omega, - show (fuel + 7 + 8 : Nat) = fuel + 2 + 13 from by omega, - show (2 : Nat) = ([(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] : - List (Nat × List EvmYul.Yul.Ast.Stmt)).length from rfl] at hReduction - have h := simpleStorageNativeContract_dispatcherExec_retrieveHit_error_via_reduction - fuel (Backends.freshNativeSwitchId reservedNames n0) - [(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] - storeBody' retrieveBody' tx storage observableSlots err - hSelector rfl ?_ hReduction - · rw [show fuel + ([(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] : - List (Nat × List EvmYul.Yul.Ast.Stmt)).length + 19 = fuel + 21 from rfl] at h - exact h - · rintro (_ | ⟨⟨_, _⟩, rest⟩) suffix hDecomp - · exfalso - simp only [List.nil_append, List.cons.injEq, Prod.mk.injEq] at hDecomp - exact absurd hDecomp.1.1 (by decide) - · simp only [List.cons_append, List.cons.injEq] at hDecomp - obtain ⟨_, hRest⟩ := hDecomp - cases rest with - | nil => simp only [List.nil_append, List.cons.injEq] at hRest - obtain ⟨_, hSuf⟩ := hRest; subst hSuf; simpa using hBody' - | cons _ _ => simp at hRest +private theorem bridgedExpr_dispatch_iszero_ident (name : String) : + BridgedExpr + (Compiler.Yul.YulExpr.call "iszero" [Compiler.Yul.YulExpr.ident name]) := by + refine BridgedExpr.call "iszero" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_singleton] at hMem + subst hMem + exact BridgedExpr.ident name -theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete - (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (err : EvmYul.Yul.Exception) - (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hBody : ∀ (reservedNames : List String) (n0 : Nat), - EvmYul.Yul.exec (fuel + 8) (.Block simpleStorageLoweredRetrieveCaseBody) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState - (Backends.freshNativeSwitchId reservedNames n0) - tx storage observableSlots) = - .error err) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error err := by - refine simpleStorageNativeContract_dispatcherExec_retrieveHit_error - fuel tx storage observableSlots err hSelector hNoWrap ?_ - intro reservedNames n0 _ _ retrieveBody' hShape - obtain ⟨_, hRetrieve⟩ := simpleStorageLoweredHitCasesShape_concrete hShape - rw [hRetrieve] - exact hBody reservedNames n0 +private theorem callvalueGuard_bridged_local : + BridgedStmt Compiler.CodegenCommon.callvalueGuard := by + unfold Compiler.CodegenCommon.callvalueGuard + exact bridgedStmt_if_of_bridgedStmts bridgedExpr_dispatch_callvalue + BridgedStmts_singleton_revert_zero -theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail - (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (err : EvmYul.Yul.Exception) - (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hTail : ∀ (reservedNames : List String) (n0 : Nat), - EvmYul.Yul.exec (fuel + 7) (.Block simpleStorageLoweredRetrieveCaseBodyTail) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState - (Backends.freshNativeSwitchId reservedNames n0) - tx storage observableSlots) = - .error err) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error err := by - refine simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete - fuel tx storage observableSlots err hSelector hNoWrap ?_ - intro reservedNames n0 - exact exec_block_simpleStorageLoweredRetrieveCaseBody_head_strip_error - (fuel + 6) _ _ err (hTail reservedNames n0) +private theorem calldatasizeGuard_bridged_local (numParams : Nat) : + BridgedStmt (Compiler.CodegenCommon.calldatasizeGuard numParams) := by + unfold Compiler.CodegenCommon.calldatasizeGuard + exact bridgedStmt_if_of_bridgedStmts + (bridgedExpr_dispatch_calldatasize_lt (4 + numParams * 32)) + BridgedStmts_singleton_revert_zero -/-- Retrieve-case dual of `_storeHit_error_concrete_tail2`. -/ -theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail2 - (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (err : EvmYul.Yul.Exception) - (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hMsgValue : tx.msgValue % EvmYul.UInt256.size = 0) - (hTail2 : ∀ (reservedNames : List String) (n0 : Nat), - EvmYul.Yul.exec (fuel + 6) - (.Block simpleStorageLoweredRetrieveCaseBodyTail2) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState - (Backends.freshNativeSwitchId reservedNames n0) - tx storage observableSlots) = - .error err) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error err := by - refine simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail - fuel tx storage observableSlots err hSelector hNoWrap ?_ - intro reservedNames n0 - have hWei : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.weiValue = - (⟨0⟩ : EvmYul.Literal) := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_weiValue] - apply congrArg EvmYul.UInt256.mk - apply Fin.ext - simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256, - EvmYul.UInt256.ofNat, Fin.ofNat] using hMsgValue - have hT2 := hTail2 reservedNames n0 - show EvmYul.Yul.exec (fuel + 7) (.Block simpleStorageLoweredRetrieveCaseBodyTail) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (.Ok _ _) = .error err - exact exec_block_simpleStorageLoweredRetrieveCaseBodyTail_callvalue_strip_error - fuel _ _ _ err hWei hT2 +private theorem dispatchBody_bridged_local (payable : Bool) (label : String) + (body : List Compiler.Yul.YulStmt) (hBody : BridgedStmts body) : + BridgedStmts (Compiler.CodegenCommon.dispatchBody payable label body) := by + unfold Compiler.CodegenCommon.dispatchBody + cases payable <;> + simp only [Bool.false_eq_true, ite_false, ite_true, + List.singleton_append] + · exact BridgedStmts_cons_comment label + (BridgedStmts_cons callvalueGuard_bridged_local hBody) + · exact BridgedStmts_cons_comment label hBody -/-- Retrieve-case wrapper that further shrinks the body-exec obligation by -also stripping the inner `if lt(calldatasize(), 4) {…}` argument-length revert -guard. The user supplies the tail3 obligation (the 2-statement -`mstore(0, sload(0)); return(0, 32)` core) and the wrapper discharges both -the callvalue and lt-calldatasize guards via the strip lemmas. The -calldata-size assumptions are derived automatically from `hNoWrap` and -`initialState_calldataSize`. -/ -theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail3 - (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (err : EvmYul.Yul.Exception) - (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hMsgValue : tx.msgValue % EvmYul.UInt256.size = 0) - (hTail3 : ∀ (reservedNames : List String) (n0 : Nat), - EvmYul.Yul.exec (fuel + 9) - (.Block simpleStorageLoweredRetrieveCaseBodyTail3) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState - (Backends.freshNativeSwitchId reservedNames n0) - tx storage observableSlots) = - .error err) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - (fuel + 25) Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error err := by - refine simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail2 - (fuel + 4) tx storage observableSlots err hSelector hNoWrap hMsgValue ?_ - intro reservedNames n0 - have hT3 := hTail3 reservedNames n0 - have hSize : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.calldata.size < - EvmYul.UInt256.size := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] - exact hNoWrap - have hGe : - 4 ≤ (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.calldata.size := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] - exact Nat.le_add_right 4 _ - show EvmYul.Yul.exec ((fuel + 4) + 6) - (.Block simpleStorageLoweredRetrieveCaseBodyTail2) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (.Ok _ _) = .error err - exact exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error - fuel _ _ _ err hSize hGe hT3 +private theorem defaultDispatchCase_bridged_local + (fallback receive : Option Compiler.IREntrypoint) + (hFallback : ∀ fb, fallback = some fb → BridgedStmts fb.body) + (hReceive : ∀ rc, receive = some rc → BridgedStmts rc.body) : + BridgedStmts + (Compiler.CodegenCommon.defaultDispatchCase fallback receive) := by + cases receive with + | none => + cases fallback with + | none => + unfold Compiler.CodegenCommon.defaultDispatchCase + exact BridgedStmts_singleton_revert_zero + | some fb => + unfold Compiler.CodegenCommon.defaultDispatchCase + exact dispatchBody_bridged_local fb.payable "fallback()" fb.body + (hFallback fb rfl) + | some rc => + cases fallback with + | none => + unfold Compiler.CodegenCommon.defaultDispatchCase + refine BridgedStmts_singleton_block ?_ + exact BridgedStmts_cons_let "__is_empty_calldata" _ + bridgedExpr_dispatch_empty_calldata + (BridgedStmts_cons_if + (BridgedExpr.ident "__is_empty_calldata") + (dispatchBody_bridged_local rc.payable "receive()" rc.body + (hReceive rc rfl)) + (BridgedStmts_cons_if + (bridgedExpr_dispatch_iszero_ident "__is_empty_calldata") + BridgedStmts_singleton_revert_zero + BridgedStmts_nil)) + | some fb => + unfold Compiler.CodegenCommon.defaultDispatchCase + refine BridgedStmts_singleton_block ?_ + exact BridgedStmts_cons_let "__is_empty_calldata" _ + bridgedExpr_dispatch_empty_calldata + (BridgedStmts_cons_if + (BridgedExpr.ident "__is_empty_calldata") + (dispatchBody_bridged_local rc.payable "receive()" rc.body + (hReceive rc rfl)) + (BridgedStmts_cons_if + (bridgedExpr_dispatch_iszero_ident "__is_empty_calldata") + (dispatchBody_bridged_local fb.payable "fallback()" fb.body + (hFallback fb rfl)) + BridgedStmts_nil)) -noncomputable def simpleStorageNativeDispatcherFuel : Nat := - sizeOf [Compiler.CodegenCommon.buildSwitch - simpleStorageIRContract.functions none none] +private theorem switchCases_bridged_local + (funcs : List Compiler.IRFunction) + (hFunctions : ∀ fn, fn ∈ funcs → BridgedStmts fn.body) : + ∀ scrutinee value body, + (funcs.map (fun fn => + (fn.selector, + Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" + ([Compiler.CodegenCommon.calldatasizeGuard fn.params.length] ++ + fn.body)))).find? + (fun x => decide (x.fst = scrutinee)) = + some (value, body) → + BridgedStmts body := by + intro scrutinee value body hFind + have hMem : + (value, body) ∈ funcs.map (fun fn => + (fn.selector, + Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" + ([Compiler.CodegenCommon.calldatasizeGuard fn.params.length] ++ + fn.body))) := + List.mem_of_find?_eq_some hFind + rcases List.mem_map.mp hMem with ⟨fn, hFn, hEq⟩ + cases hEq + exact dispatchBody_bridged_local fn.payable s!"{fn.name}()" + ([Compiler.CodegenCommon.calldatasizeGuard fn.params.length] ++ fn.body) + (BridgedStmts_cons (calldatasizeGuard_bridged_local fn.params.length) + (hFunctions fn hFn)) -/-- Lower bound on the SimpleStorage native dispatcher fuel constant for -the retrieve-hit and store-hit bridges, which use the `_concrete_tail3` -chain that produces dispatcher exec at `fuel + 25`. -/ -theorem simpleStorageNativeDispatcherFuel_ge_25 : - simpleStorageNativeDispatcherFuel ≥ 25 := by - unfold simpleStorageNativeDispatcherFuel - decide +private theorem buildSwitch_bridged_local + (funcs : List Compiler.IRFunction) + (fallback receive : Option Compiler.IREntrypoint) + (hFunctions : ∀ fn, fn ∈ funcs → BridgedStmts fn.body) + (hFallback : ∀ fb, fallback = some fb → BridgedStmts fb.body) + (hReceive : ∀ rc, receive = some rc → BridgedStmts rc.body) : + BridgedStmt + (Compiler.CodegenCommon.buildSwitch funcs fallback receive false) := by + unfold Compiler.CodegenCommon.buildSwitch + exact bridgedStmt_block_of_bridgedStmts + (BridgedStmts_cons_let "__has_selector" _ + bridgedExpr_dispatch_has_selector + (BridgedStmts_cons_if + (bridgedExpr_dispatch_iszero_ident "__has_selector") + (defaultDispatchCase_bridged_local fallback receive hFallback hReceive) + (BridgedStmts_cons_if + (BridgedExpr.ident "__has_selector") + (BridgedStmts_singleton_switch + bridgedExpr_dispatch_selector + (switchCases_bridged_local funcs hFunctions) + (by + intro body hBody + cases hBody + exact defaultDispatchCase_bridged_local fallback receive + hFallback hReceive)) + BridgedStmts_nil))) -theorem simpleStorageNativeDispatcherFuel_ge_21 : - simpleStorageNativeDispatcherFuel ≥ 21 := by - exact Nat.le_trans (by decide) simpleStorageNativeDispatcherFuel_ge_25 +private theorem mappingSlotFuncAt_bridged_local (scratchBase : Nat) : + BridgedStmt (Compiler.CodegenCommon.mappingSlotFuncAt scratchBase) := by + unfold Compiler.CodegenCommon.mappingSlotFuncAt + exact bridgedStmt_funcDef "mappingSlot" ["baseSlot", "key"] ["slot"] _ -/-- Native dispatcher exec at exactly `simpleStorageNativeDispatcherFuel` -reduces to `.error Revert` for the selector-miss class. -/ -theorem simpleStorageNativeContract_dispatcherExec_selectorMiss_revert_atFuel - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (hSelectorRange : tx.functionSelector % Compiler.Constants.selectorModulus - < EvmYul.UInt256.size) - (hSelMissStore : tx.functionSelector % Compiler.Constants.selectorModulus - ≠ 0x6057361d) - (hSelMissRetrieve : tx.functionSelector % Compiler.Constants.selectorModulus - ≠ 0x2e64cec1) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - simpleStorageNativeDispatcherFuel - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error EvmYul.Yul.Exception.Revert := by - have hReshape : simpleStorageNativeDispatcherFuel = - (simpleStorageNativeDispatcherFuel - 21) + 21 := - (Nat.sub_add_cancel simpleStorageNativeDispatcherFuel_ge_21).symm - rw [hReshape] - exact simpleStorageNativeContract_dispatcherExec_selectorMiss_revert - (simpleStorageNativeDispatcherFuel - 21) - (tx.functionSelector % Compiler.Constants.selectorModulus) - tx storage observableSlots - rfl hSelectorRange hSelMissStore hSelMissRetrieve hNoWrap +private theorem runtimeCode_bridged_local + (contract : Compiler.IRContract) + (hFunctions : ∀ fn, fn ∈ contract.functions → BridgedStmts fn.body) + (hFallback : + ∀ fb, contract.fallbackEntrypoint = some fb → BridgedStmts fb.body) + (hReceive : + ∀ rc, contract.receiveEntrypoint = some rc → BridgedStmts rc.body) + (hInternals : BridgedStmts contract.internalFunctions) : + BridgedStmts (Compiler.CodegenCommon.runtimeCode contract) := by + unfold Compiler.CodegenCommon.runtimeCode + cases contract.usesMapping + · exact BridgedStmts_snoc hInternals + (buildSwitch_bridged_local contract.functions + contract.fallbackEntrypoint contract.receiveEntrypoint hFunctions + hFallback hReceive) + · simp only [ite_true] + exact BridgedStmts_cons (mappingSlotFuncAt_bridged_local 0) + (BridgedStmts_snoc hInternals + (buildSwitch_bridged_local contract.functions + contract.fallbackEntrypoint contract.receiveEntrypoint hFunctions + hFallback hReceive)) -/-- Closed-form `interpretIR` reduction for the SimpleStorage selector-miss -class. Given the two raw selector mismatches (`≠ 0x6057361d` and -`≠ 0x2e64cec1`), `interpretIR` falls into the `find?`-`none` branch and returns -the trivial reverted shape with storage and events untouched. -/ -theorem interpretIR_simpleStorage_selectorMiss - (tx : IRTransaction) (initialState : IRState) - (hSelMissStore : tx.functionSelector ≠ 0x6057361d) - (hSelMissRetrieve : tx.functionSelector ≠ 0x2e64cec1) : - interpretIR simpleStorageIRContract tx initialState = - { success := false - returnValue := none - finalStorage := initialState.storage - finalMappings := Compiler.Proofs.storageAsMappings initialState.storage - events := initialState.events } := by - unfold interpretIR - simp only [simpleStorageIRContract, List.find?] - have hstore : (0x6057361d == tx.functionSelector) = false := by - simp [BEq.beq, hSelMissStore.symm] - have hretrieve : (0x2e64cec1 == tx.functionSelector) = false := by - simp [BEq.beq, hSelMissRetrieve.symm] - simp [hstore, hretrieve] +/-- The selected native-harness switch case for a compiled external function is +bridged whenever the compiled function body is bridged. This packages the +generated dispatch guards (`callvalue`/`calldatasize`) around the body in the +same shape consumed by selector-hit native dispatcher lemmas. -/ +theorem switchCaseBody_bridged_of_body + (fn : IRFunction) + (hBody : Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) := by + have hCase := + switchCases_bridged_local + [fn] + (by + intro fn' hmem + simp only [List.mem_singleton] at hmem + subst fn' + exact hBody) + fn.selector fn.selector + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) + (by + simp [Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody]) + simpa using hCase -/-- Closed-form `interpretIR` reduction for the SimpleStorage retrieve-hit -class. Given the raw selector match (`= 0x2e64cec1`), `interpretIR` enters the -`retrieve` body which is read-only on storage: it loads slot 0 via `sload`, -mirrors it into memory[0..32] via `mstore`, and returns those 32 bytes. The -returned word equals `(state.storage (IRStorageSlot.ofNat 0)).toNat` (where `state` is -`initialState.withTx tx`). Storage and events are unchanged. +/-- Supported compiler output gives a bridged selected switch-case body for +every emitted external function. -/ +theorem generatedRuntimeSwitchCaseBodiesBridged_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) := by + intro fn hmem + exact switchCaseBody_bridged_of_body fn + (generatedRuntimeExternalBodiesBridged_of_compile_ok_supported + hCompile hSupported fn hmem) - After Phase 1 of the IR storage refactor, - `state.storage (IRStorageSlot.ofNat 0) : IRStorageWord` is `UInt256`-bounded, - so `(state.storage (IRStorageSlot.ofNat 0)).toNat < 2^256`. This is the -IR-side input to `simpleStorageNativeRetrieveHitBridge` Step A. -/ -theorem interpretIR_simpleStorage_retrieveHit - (tx : IRTransaction) (initialState : IRState) - (hSel : tx.functionSelector = 0x2e64cec1) : - interpretIR simpleStorageIRContract tx initialState = - { success := true - returnValue := some ((initialState.storage (IRStorageSlot.ofNat 0)).toNat) - finalStorage := initialState.storage - finalMappings := Compiler.Proofs.storageAsMappings initialState.storage - events := initialState.events } := by - have hstore : (0x6057361d == tx.functionSelector) = false := by - simp [BEq.beq, hSel] - have hretrieve : (0x2e64cec1 == tx.functionSelector) = true := by - simp [BEq.beq, hSel] - -- Closed-form evaluation of the retrieve body for any fuel ≥ 2. - have hbody : ∀ (n : Nat) (s : IRState), 2 ≤ n → - execIRStmts (n + 1) s - [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" - [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), - Yul.YulStmt.expr (Yul.YulExpr.call "return" - [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] = - .return ((s.storage (IRStorageSlot.ofNat 0)).toNat) - { s with memory := fun o => - if o = 0 then (s.storage (IRStorageSlot.ofNat 0)).toNat else s.memory o } := by - intro n s hn - obtain ⟨k, rfl⟩ : ∃ k, n = k + 2 := ⟨n - 2, by omega⟩ - -- Fuel `k + 2 + 1 = k + 3` is `Nat.succ (Nat.succ (Nat.succ k))`, allowing - -- both the outer `execIRStmts` and the inner `execIRStmt` to step. - simp +decide only [execIRStmts, execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, - Compiler.Proofs.abstractLoadStorageOrMapping, - Option.bind_some, bind, pure, ↓reduceIte] - -- The retrieve body has at least 2 statements, so `sizeOf body ≥ 2` by - -- direct computation on the auto-derived size measure. - have hsize : 2 ≤ sizeOf - ([Yul.YulStmt.expr (Yul.YulExpr.call "mstore" - [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), - Yul.YulStmt.expr (Yul.YulExpr.call "return" - [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] : List Yul.YulStmt) := by - decide - unfold interpretIR - simp only [simpleStorageIRContract, List.find?, hstore, hretrieve, - List.length_nil, Nat.zero_le, ↓reduceDIte] - -- Now goal involves `execIRFunction retrieveFn tx.args state'`. - unfold execIRFunction - simp only [List.zip_nil_left, List.foldl_nil] - -- Goal: `match execIRStmts (sizeOf body + 1) state' body with ... = ...`. - rw [hbody _ _ hsize] +/-- The weaker mapping-write-supported compiler output gives a bridged selected +switch-case body for every emitted external function once mapping-write +slot-safety is supplied. -/ +theorem generatedRuntimeSwitchCaseBodiesBridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) := by + intro fn hmem + exact switchCaseBody_bridged_of_body fn + (generatedRuntimeExternalBodiesBridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + hCompile hSupported hSafety fn hmem) -/-- Closed-form `interpretIR` reduction for the SimpleStorage store-hit class -when the ABI argument is present. The IR setter writes the first calldata word -to bounded storage slot zero and stops successfully. -/ -theorem interpretIR_simpleStorage_storeHit_arg - (tx : IRTransaction) (initialState : IRState) - (arg : Nat) (rest : List Nat) - (hSel : tx.functionSelector = 0x6057361d) - (hArgs : tx.args = arg :: rest) : - interpretIR simpleStorageIRContract tx initialState = - { success := true - returnValue := none - finalStorage := - Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 - (arg % evmModulus) - finalMappings := - Compiler.Proofs.storageAsMappings - (Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 - (arg % evmModulus)) - events := initialState.events } := by - have hstore : (0x6057361d == tx.functionSelector) = true := by - simp [BEq.beq, hSel] - have hbody : ∀ (n : Nat) (s : IRState), 3 ≤ n → - execIRStmts (n + 1) s - [Yul.YulStmt.let_ "value" (Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]), - Yul.YulStmt.expr (Yul.YulExpr.call "sstore" - [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), - Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])] = - .stop - { s.setVar "value" (Compiler.Proofs.YulGeneration.calldataloadWord - s.selector s.calldata 4) with - storage := Compiler.Proofs.abstractStoreStorageOrMapping - s.storage 0 (Compiler.Proofs.YulGeneration.calldataloadWord - s.selector s.calldata 4) } := by - intro n s hn - obtain ⟨k, rfl⟩ : ∃ k, n = k + 3 := ⟨n - 3, by omega⟩ - simp +decide [execIRStmts, execIRStmt, evalIRExpr, IRState.getVar, - IRState.setVar] - have hsize : 3 ≤ sizeOf - ([Yul.YulStmt.let_ "value" (Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]), - Yul.YulStmt.expr (Yul.YulExpr.call "sstore" - [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), - Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])] : List Yul.YulStmt) := by - decide - unfold interpretIR - simp only [simpleStorageIRContract, List.find?, hstore, List.length_cons, - List.length_nil, Nat.reduceAdd] - unfold execIRFunction - simp only [hArgs, List.zip_cons_cons, List.zip_nil_left, List.foldl_cons, - List.foldl_nil] - rw [hbody _ _ hsize] - simp [IRState.setVar, Compiler.Proofs.abstractStoreStorageOrMapping_eq, - Compiler.Proofs.YulGeneration.calldataloadWord, evmModulus] +theorem generatedRuntimeSelectedSwitchCaseBodyBridged_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) := + generatedRuntimeSwitchCaseBodiesBridged_of_compile_ok_supported + hCompile hSupported fn (List.mem_of_find?_eq_some hFind) -/-- Closed-form `interpretIR` reduction for the SimpleStorage store-hit class -when calldata is too short for the single setter argument. The dispatcher -selects the function, but the IR arity guard fails before executing the body. -/ -theorem interpretIR_simpleStorage_storeHit_short - (tx : IRTransaction) (initialState : IRState) - (hSel : tx.functionSelector = 0x6057361d) - (hShort : tx.args = []) : - interpretIR simpleStorageIRContract tx initialState = - { success := false - returnValue := none - finalStorage := initialState.storage - finalMappings := Compiler.Proofs.storageAsMappings initialState.storage - events := initialState.events } := by - have hstore : (0x6057361d == tx.functionSelector) = true := by - simp [BEq.beq, hSel] - unfold interpretIR - simp [simpleStorageIRContract, hstore, hShort] +/-- Supported compiler output gives a bridged selected direct user function +body. This is the source-fragment witness paired with +`lowerStmtsNativeWithSwitchIds_selectedFunctionBody_exists_of_compile_ok_supported` +for the remaining native function-body semantics bridge. -/ +theorem generatedRuntimeSelectedFunctionBodyBridged_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body := + generatedRuntimeExternalBodiesBridged_of_compile_ok_supported + hCompile hSupported fn (List.mem_of_find?_eq_some hFind) -/-- Native dispatcher exec at exactly `simpleStorageNativeDispatcherFuel` -reduces to `.error (YulHalt (.Ok shared3 _) ⟨1⟩)` for the retrieve-hit class, -where `shared3` is the closed-form shared state after the -`mstore(0, sload(0))` and `return(0, 32)` updates. The Yul varStore inside -the halt state depends on the fresh switch identifier (which the dispatcher -chose internally), so it is left existentially quantified — `projectResult` -on `.error (YulHalt _ _)` ignores the varStore, so this is sufficient for -the bridge proof. Composes the body-level closed form -`exec_block_simpleStorageLoweredRetrieveCaseBody_halt` with -`_retrieveHit_error_via_reduction` after opening the `_sourceLowered` -existential and pinning `cases'` via `_lowered_shape` and -`_lowered_concrete`. The `_concrete_tail*` chain is bypassed because it -universally quantifies over `(reservedNames, n0)` against a single fixed -`err`, which is incompatible with the switchId-dependent varStore inside -the halt-error term. -/ -theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_halt_atFuel - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hMsgValue : tx.msgValue % EvmYul.UInt256.size = 0) : - let shared := (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState - let p := shared.sload (EvmYul.UInt256.ofNat 0) - let shared1 : EvmYul.SharedState .Yul := { shared with toState := p.1 } - let shared2 : EvmYul.SharedState .Yul := - { shared1 with - toMachineState := - shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) p.2 } - let shared3 : EvmYul.SharedState .Yul := - { shared2 with - toMachineState := - shared2.toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } - ∃ store : EvmYul.Yul.VarStore, - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - simpleStorageNativeDispatcherFuel - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store) ⟨1⟩) := by - -- Bring the let-bound names from the goal into the local context. - intro shared p shared1 shared2 shared3 - -- Reshape dispatcher fuel to `g + 25` where `g := dispatcherFuel - 25`. - set g := simpleStorageNativeDispatcherFuel - 25 with hg_def - have hReshape : simpleStorageNativeDispatcherFuel = g + 25 := - (Nat.sub_add_cancel simpleStorageNativeDispatcherFuel_ge_25).symm - rw [hReshape] - -- Open the `_sourceLowered` existential at `peeledFuel := g + 11`, so the - -- dispatcher LHS lands at `(g + 11) + 14 = g + 25`. - obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := - simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - (g + 11) tx storage observableSlots hNoWrap - -- Pin `cases'` to the two-element shape. - obtain ⟨storeBody', retrieveBody', hCases⟩ := - simpleStorageBuildSwitchSourceCases_lowered_shape reservedNames _ midN - cases' hLowerCases - subst hCases - -- Pin the lowered bodies to the concrete forms. - obtain ⟨hStoreBody, hRetrieveBody⟩ := - simpleStorageLoweredHitCasesShape_concrete hLowerCases - subst hStoreBody - subst hRetrieveBody - -- The chained-insert varStore for the dispatcher hit-body input state. - set switchId := Backends.freshNativeSwitchId reservedNames n0 with hSw - let store_body : EvmYul.Yul.VarStore := - ((((∅ : EvmYul.Yul.VarStore).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)).insert - (Backends.nativeSwitchDiscrTempName switchId) - (EvmYul.UInt256.ofNat - (tx.functionSelector % Compiler.Constants.selectorModulus))).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 0)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1) - -- Provide `store := store_body` for the existential. - refine ⟨store_body, ?_⟩ - -- Discharge the body-level closed form via `_RetrieveCaseBody_halt`. - have hWei : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.weiValue = - (⟨0⟩ : EvmYul.Literal) := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_weiValue] - apply congrArg EvmYul.UInt256.mk - apply Fin.ext - simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256, - EvmYul.UInt256.ofNat, Fin.ofNat] using hMsgValue - have hSize : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.calldata.size < - EvmYul.UInt256.size := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] - exact hNoWrap - have hGe : - 4 ≤ (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.calldata.size := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] - exact Nat.le_add_right 4 _ - have hBodyHalt := - exec_block_simpleStorageLoweredRetrieveCaseBody_halt g - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState - store_body hWei hSize hGe - -- Reshape `hExec` into the form expected by `_via_reduction`'s - -- `hReduction` parameter. - have hReduction := hExec - rw [show (g + 11 + 14 : Nat) = (g + 4) + 2 + 19 from by omega, - show (g + 11 + 8 : Nat) = (g + 4) + 2 + 13 from by omega, - show (2 : Nat) = ([(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : - List (Nat × List EvmYul.Yul.Ast.Stmt)).length from rfl] at hReduction - -- Body-execution premise of `_via_reduction`: only valid decomposition is - -- `pre = [(0x6057361d, store)]`, `suffix = []`. Body fuel is - -- `(g + 4 + 1) + 0 + 7 = g + 12`, matching `hBodyHalt`. - have hBodyExec : ∀ pre suffix, - ([(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : - List (Nat × List EvmYul.Yul.Ast.Stmt)) = - pre ++ (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody) :: suffix → - EvmYul.Yul.exec (((g + 4) + 1) + suffix.length + 7) - (.Block simpleStorageLoweredRetrieveCaseBody) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState switchId tx storage - observableSlots) = - .error (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store_body) ⟨1⟩) := by - rintro pre suffix hDecomp - cases pre with - | nil => - simp only [List.nil_append, List.cons.injEq, Prod.mk.injEq] at hDecomp - exfalso - exact absurd hDecomp.1.1 (by decide) - | cons _ rest => - simp only [List.cons_append, List.cons.injEq] at hDecomp - obtain ⟨_, hRest⟩ := hDecomp - cases rest with - | nil => - simp only [List.nil_append, List.cons.injEq] at hRest - obtain ⟨_, hSuf⟩ := hRest - subst hSuf - simpa [simpleStorageDispatcherHitBodyInputState] using hBodyHalt - | cons _ _ => simp at hRest - -- Apply `_retrieveHit_error_via_reduction` at `fuel := g + 4` with - -- `err := YulHalt (.Ok shared3 store_body) ⟨1⟩`. - have h := simpleStorageNativeContract_dispatcherExec_retrieveHit_error_via_reduction - (g + 4) switchId - [(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] - simpleStorageLoweredStoreCaseBody simpleStorageLoweredRetrieveCaseBody - tx storage observableSlots - (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store_body) ⟨1⟩) - hSelector rfl hBodyExec hReduction - -- `h` has dispatcher fuel `(g + 4) + cases'.length + 19`. Reshape to `g + 25`. - have hLen : - ([(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : - List (Nat × List EvmYul.Yul.Ast.Stmt)).length = 2 := rfl - rw [hLen, show (g + 4) + 2 + 19 = g + 25 from by omega] at h - exact h +theorem generatedRuntimeSelectedSwitchCaseBodyBridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) := + generatedRuntimeSwitchCaseBodiesBridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + hCompile hSupported hSafety fn (List.mem_of_find?_eq_some hFind) -/-- Native dispatcher exec at exactly `simpleStorageNativeDispatcherFuel` +/-- The selected native-harness switch case contains no nested function +definitions whenever the compiled function body contains none. -/ +theorem switchCaseBody_noFuncDefs_of_body + (fn : IRFunction) + (hBody : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false) : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + false := by + unfold Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody + exact Compiler.Proofs.YulGeneration.Backends.Native.dispatchBody_noFuncDefs + fn.payable s!"{fn.name}()" + ([Compiler.CodegenCommon.calldatasizeGuard fn.params.length] ++ fn.body) + (by + simp [Compiler.CodegenCommon.calldatasizeGuard, + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtContainsFuncDef, + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef, + hBody]) + +/-- Supported compiler output emits no internal helper bodies; this is the +bridgeable-body analogue of the generated-runtime internal no-func-def witness. -/ +theorem generatedRuntimeInternalBodiesBridged_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + ∀ name params rets body, + Yul.YulStmt.funcDef name params rets body ∈ irContract.internalFunctions → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts body := by + intro name params rets body hmem + have hInternalNil : irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hInternalNil] at hmem + simp at hmem + +/-- The weaker mapping-write-supported fragment emits no internal helper bodies, +so internal body bridgeability is immediate. -/ +theorem generatedRuntimeInternalBodiesBridged_of_compile_ok_supported_except_mapping_writes + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) : + ∀ name params rets body, + Yul.YulStmt.funcDef name params rets body ∈ irContract.internalFunctions → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts body := by + intro name params rets body hmem + have hInternalNil : irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_internalFunctions_nil_except_mapping_writes + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hInternalNil] at hmem + simp at hmem + +/-- `SupportedSpec` discharges all body witnesses required by the retargeting +bridge theorem for the `emitYul` runtime. -/ +theorem emitYul_runtimeCode_bridged_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts + (Compiler.emitYul irContract).runtimeCode := by + simpa [Compiler.emitYul] using + runtimeCode_bridged_local + irContract + (generatedRuntimeExternalBodiesBridged_of_compile_ok_supported + hCompile hSupported) + (generatedRuntimeFallbackBodyBridged_of_compile_ok_supported + hCompile hSupported) + (generatedRuntimeReceiveBodyBridged_of_compile_ok_supported + hCompile hSupported) + (by + have hInternalNil : irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hInternalNil] + exact Compiler.Proofs.YulGeneration.Backends.BridgedStmts_nil) + +/-- The weaker mapping-write-supported fragment discharges the retargeting +bridge theorem for the `emitYul` runtime when actual mapping writes are +slot-safe. -/ +theorem emitYul_runtimeCode_bridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts + (Compiler.emitYul irContract).runtimeCode := by + simpa [Compiler.emitYul] using + runtimeCode_bridged_local + irContract + (generatedRuntimeExternalBodiesBridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + hCompile hSupported hSafety) + (generatedRuntimeFallbackBodyBridged_of_compile_ok_supported_except_mapping_writes + hCompile hSupported) + (generatedRuntimeReceiveBodyBridged_of_compile_ok_supported_except_mapping_writes + hCompile hSupported) + (by + have hInternalNil : irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_internalFunctions_nil_except_mapping_writes + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hInternalNil] + exact Compiler.Proofs.YulGeneration.Backends.BridgedStmts_nil) + +/-- Supported compiler output has no internal helper bodies that can contain +nested function definitions. -/ +theorem generatedRuntimeInternalBodiesHaveNoFuncDefs_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + ∀ name params rets body, + Yul.YulStmt.funcDef name params rets body ∈ irContract.internalFunctions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef body = false := by + intro name params rets body hmem + have hInternalNil : irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hInternalNil] at hmem + simp at hmem + +/-- The weaker mapping-write-supported compiler output has no internal helper +bodies that can contain nested function definitions. -/ +theorem generatedRuntimeInternalBodiesHaveNoFuncDefs_of_compile_ok_supported_except_mapping_writes + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) : + ∀ name params rets body, + Yul.YulStmt.funcDef name params rets body ∈ irContract.internalFunctions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef body = false := by + intro name params rets body hmem + have hInternalNil : irContract.internalFunctions = [] := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_internalFunctions_nil_except_mapping_writes + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile) + rw [hInternalNil] at hmem + simp at hmem + +/-- Source-level body closure discharges the generated runtime fragment's +external-function-body shape witness for supported compiler output. -/ +theorem generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hBodyNoFuncDefs : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ bodyStmts, + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .calldata [] false (entry.1.params.map (·.name)) [] entry.1.body = + Except.ok bodyStmts → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + bodyStmts = false) : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false := + compiledExternalFunctions_noFuncDefs_of_static_params_and_body + spec.fields spec.events spec.errors + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_compiled_functions + spec selectors hSupported irContract hCompile) + hStaticParams hBodyNoFuncDefs + +theorem generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false := + compiledExternalFunctions_noFuncDefs_of_safe_static + spec.fields spec.events spec.errors + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_compiled_functions + spec selectors hSupported irContract hCompile) + hStaticParams hSafeBodies + +/-- The weaker mapping-write-supported compiler output emits external bodies +without nested function definitions once body-local mapping-write slot-safety +evidence is supplied. -/ +theorem generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false := + compiledExternalFunctions_noFuncDefs_of_safe_static + spec.fields spec.events spec.errors + (Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions_except_mapping_writes + spec selectors hSupported irContract hCompile) + (generatedRuntimeStaticScalarParams_of_supported_except_mapping_writes + hSupported) + (generatedRuntimeSafeBodies_of_supported_except_mapping_writes_stmt_safety + hSupported hSafety) + +/-- Supported compiler output gives selected switch-case bodies without nested +function definitions for every emitted external function. -/ +theorem generatedRuntimeSwitchCaseBodiesHaveNoFuncDefs_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + false := by + intro fn hmem + exact switchCaseBody_noFuncDefs_of_body fn + (generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + hCompile hSupported hStaticParams hSafeBodies fn hmem) + +/-- The weaker mapping-write-supported compiler output gives selected +switch-case bodies without nested function definitions once mapping-write +slot-safety is supplied. -/ +theorem generatedRuntimeSwitchCaseBodiesHaveNoFuncDefs_of_compile_ok_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + false := by + intro fn hmem + exact switchCaseBody_noFuncDefs_of_body fn + (generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_supported_except_mapping_writes_stmt_safety + hCompile hSupported hSafety fn hmem) + +theorem generatedRuntimeSelectedSwitchCaseBodyHasNoFuncDefs_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + false := + generatedRuntimeSwitchCaseBodiesHaveNoFuncDefs_of_compile_ok_supported + hCompile hSupported hStaticParams hSafeBodies fn + (List.mem_of_find?_eq_some hFind) + +theorem generatedRuntimeSelectedSwitchCaseBodyHasNoFuncDefs_of_compile_ok_supported_safe + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + false := + generatedRuntimeSelectedSwitchCaseBodyHasNoFuncDefs_of_compile_ok_supported + hCompile hSupported (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) hFind + +theorem generatedRuntimeSelectedSwitchCaseBodyHasNoFuncDefs_of_compile_ok_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + false := + generatedRuntimeSwitchCaseBodiesHaveNoFuncDefs_of_compile_ok_supported_except_mapping_writes_stmt_safety + hCompile hSupported hSafety fn (List.mem_of_find?_eq_some hFind) + +/-- Supported compiler output satisfies the native generated-runtime fragment +validator's executable predicate. -/ +theorem generatedRuntimeNativeFragment_of_compile_ok_supported_safe + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) : + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment + (Compiler.emitYul irContract).runtimeCode = true := + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment_emitYul_runtimeCode_noFallback_noReceive + irContract + (generatedRuntimePrefixFunctionNamesUnique_of_compile_ok_supported + hCompile hSupported) + (generatedRuntimeInternalsAreFuncDefs_of_compile_ok_supported + hCompile hSupported) + (generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + hCompile hSupported hStaticParams hSafeBodies) + (generatedRuntimeInternalBodiesHaveNoFuncDefs_of_compile_ok_supported + hCompile hSupported) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile) + +/-- The weaker mapping-write-supported compiler output satisfies the native +generated-runtime fragment validator once each actual mapping-write statement +has slot-safety evidence. -/ +theorem generatedRuntimeNativeFragment_of_compile_ok_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) : + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment + (Compiler.emitYul irContract).runtimeCode = true := + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment_emitYul_runtimeCode_noFallback_noReceive + irContract + (generatedRuntimePrefixFunctionNamesUnique_of_compile_ok_supported_except_mapping_writes + hCompile hSupported) + (generatedRuntimeInternalsAreFuncDefs_of_compile_ok_supported_except_mapping_writes + hCompile hSupported) + (generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_supported_except_mapping_writes_stmt_safety + hCompile hSupported hSafety) + (generatedRuntimeInternalBodiesHaveNoFuncDefs_of_compile_ok_supported_except_mapping_writes + hCompile hSupported) + (Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_noFallbackEntrypoint_except_mapping_writes + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile)) + (Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_noReceiveEntrypoint_except_mapping_writes + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile)) + +/-- Supported compiler output satisfies the native generated-runtime fragment +validator once source body closure is supplied; static-scalar parameter closure +is derived directly from `SupportedSpec`. -/ +theorem generatedRuntimeNativeFragment_of_compile_ok_supported_safeBodies + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) : + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment + (Compiler.emitYul irContract).runtimeCode = true := + generatedRuntimeNativeFragment_of_compile_ok_supported_safe + hCompile hSupported (generatedRuntimeStaticScalarParams_of_supported hSupported) + hSafeBodies + +/-- `SupportedSpec` is enough to validate the Yul runtime emitted by `emitYul` +as a generated native-runtime fragment. -/ +theorem generatedRuntimeNativeFragment_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment + (Compiler.emitYul irContract).runtimeCode = true := + generatedRuntimeNativeFragment_of_compile_ok_supported_safeBodies + hCompile hSupported (generatedRuntimeSafeBodies_of_supported hSupported) + +/-- Supported compiler output passes the native generated-runtime fragment +validator. -/ +theorem validateGeneratedRuntimeNativeFragment_of_compile_ok_supported_safe + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) : + Compiler.Proofs.YulGeneration.Backends.Native.validateGeneratedRuntimeNativeFragment + (Compiler.emitYul irContract).runtimeCode = .ok () := + Compiler.Proofs.YulGeneration.Backends.Native.validateGeneratedRuntimeNativeFragment_ok + (Compiler.emitYul irContract).runtimeCode + (generatedRuntimeNativeFragment_of_compile_ok_supported_safe + hCompile hSupported hStaticParams hSafeBodies) + +theorem validateGeneratedRuntimeNativeFragment_of_compile_ok_supported_safeBodies + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) : + Compiler.Proofs.YulGeneration.Backends.Native.validateGeneratedRuntimeNativeFragment + (Compiler.emitYul irContract).runtimeCode = .ok () := + Compiler.Proofs.YulGeneration.Backends.Native.validateGeneratedRuntimeNativeFragment_ok + (Compiler.emitYul irContract).runtimeCode + (generatedRuntimeNativeFragment_of_compile_ok_supported_safeBodies + hCompile hSupported hSafeBodies) + +/-- Executable native-fragment validation succeeds for the `emitYul` runtime of +any supported compilation result. -/ +theorem validateGeneratedRuntimeNativeFragment_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + Compiler.Proofs.YulGeneration.Backends.Native.validateGeneratedRuntimeNativeFragment + (Compiler.emitYul irContract).runtimeCode = .ok () := + validateGeneratedRuntimeNativeFragment_of_compile_ok_supported_safeBodies + hCompile hSupported (generatedRuntimeSafeBodies_of_supported hSupported) + +theorem validateGeneratedRuntimeNativeFragment_of_compile_ok_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) : + Compiler.Proofs.YulGeneration.Backends.Native.validateGeneratedRuntimeNativeFragment + (Compiler.emitYul irContract).runtimeCode = .ok () := + Compiler.Proofs.YulGeneration.Backends.Native.validateGeneratedRuntimeNativeFragment_ok + (Compiler.emitYul irContract).runtimeCode + (generatedRuntimeNativeFragment_of_compile_ok_supported_except_mapping_writes_stmt_safety + hCompile hSupported hSafety) + +/-- The direct generated-runtime `callDispatcher` result is the executable +native harness result once the supported emitted runtime lowers successfully +and its native environment is valid. -/ +private theorem nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (tx : IRTransaction) (state : IRState) (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + nativeGeneratedCallDispatcherResultOf irContract tx state observableSlots + nativeContract = + Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx state observableSlots := by + have hInterp := + Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative_eq_callDispatcher_of_lowerRuntimeContractNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx state observableSlots nativeContract + (generatedRuntimeNativeFragment_of_compile_ok_supported hCompile hSupported) + hLower hEnv + rw [hInterp] + simp [nativeGeneratedCallDispatcherResultOf, Compiler.emitYul, + Compiler.runtimeCode, Compiler.CodegenCommon.emitYul] + +private theorem nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported_except_mapping_writes_stmt_safety + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (tx : IRTransaction) (state : IRState) (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + (hSafety : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + ∀ stmt, stmt ∈ entry.1.body → + StmtMappingWriteSlotSafe spec.fields stmt) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + nativeGeneratedCallDispatcherResultOf irContract tx state observableSlots + nativeContract = + Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx state observableSlots := by + have hInterp := + Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative_eq_callDispatcher_of_lowerRuntimeContractNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx state observableSlots nativeContract + (generatedRuntimeNativeFragment_of_compile_ok_supported_except_mapping_writes_stmt_safety + hCompile hSupported hSafety) + hLower hEnv + rw [hInterp] + simp [nativeGeneratedCallDispatcherResultOf, Compiler.emitYul, + Compiler.runtimeCode, Compiler.CodegenCommon.emitYul] + +/-- Source-level compiler correctness over the direct projected +`EvmYul.Yul.callDispatcher` result. + +This is the thinnest public native composition surface: callers prove the +actual projected native result matches `interpretIR`; this theorem composes +that result match with the supported source-to-IR compiler theorem. It exposes +no generated-dispatcher oracle predicate. -/ +private theorem compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNative : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract) := by + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + hNative + +/-- Supported compiler correctness for the direct generated +`EvmYul.Yul.callDispatcher` projection, once the generated runtime has been +lowered and the native runtime interpreter is known to match the IR result. + +This is the public composition point that avoids exposing the older generated +dispatcher-exec and generated call-dispatcher match predicates. -/ +private theorem compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) + (hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract) := by + rw [ + nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported + tx (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract hcompile hSupported hLower hEnv] + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + hNativeIR + +/-- `YulTransaction.ofIR` wrapper for the direct generated `callDispatcher` +composition theorem, discharging native runtime environment validation from +representable environment facts. -/ +private theorem compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract) := + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract htxNormalized hcalldataSizeFits hcompile hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeIR + +/-- `YulTransaction.ofIR` wrapper for the direct generated `callDispatcher` +composition theorem, discharging native runtime environment validation from the +EVMYulLean global default environment. -/ +private theorem compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract) := + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract htxNormalized hcalldataSizeFits hcompile hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeIR + +/-- Supported compiler output with no mapping helper reduces native runtime +lowering to the single generated dispatcher shell. -/ +theorem lowerRuntimeContractNative_of_compile_ok_supported_noMapping + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + match Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] with + | .ok dispatcher => + .ok { dispatcher := .Block dispatcher + functions := + (∅ : + Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) } + | .error err => .error err := + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNative_emitYul_noMapping_noInternals_noFallback_noReceive + irContract hNoMapping + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile)) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile) + +/-- Successful no-mapping native lowering for supported compiler output exposes +the concrete generated dispatcher lowering and produced native contract. -/ +private theorem lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) : + ∃ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher ∧ + nativeContract = nativeContractOfDispatcher dispatcher := + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNative_emitYul_noMapping_ok_dispatcher + irContract nativeContract hNoMapping + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile)) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile) + hLower + +/-- Dispatcher-contract-shell form of +`lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher`. + +This exposes the native contract used by `EvmYul.Yul.callDispatcher` through +the helper-free generated-dispatcher shell. -/ +private theorem lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_public_dispatcher + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) : + ∃ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher ∧ + nativeContract = nativeGeneratedDispatcherContractOf dispatcher := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hCompile hSupported hNoMapping hLower with + ⟨dispatcher, hDispatcher, hContract⟩ + refine ⟨dispatcher, hDispatcher, ?_⟩ + simpa [nativeContractOfDispatcher, nativeGeneratedDispatcherContractOf] + using hContract + +/-- Supported compiler output with the mapping helper reduces native runtime +lowering to the generated dispatcher shell plus the lowered native +`mappingSlot` helper. The dispatcher is lowered under the same reserved-name +context as the full emitted runtime, because native switch lowering allocates +fresh temporaries from that context. -/ +theorem lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + match Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] with + | .ok (dispatcher, _) => + .ok { dispatcher := .Block dispatcher + functions := ((∅ : + Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) } + | .error err => .error err := + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNative_emitYul_mapping_noInternals_noFallback_noReceive_reserved + irContract hMapping + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile)) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile) + +/-- Supported compiler output gives successful native lowering for the +generated helper-free dispatcher statement. -/ +theorem lowerStmtsNative_buildSwitch_noFallback_noReceive_exists_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + ∃ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher := by + have hBodies : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false := + generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + hCompile hSupported (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) + have hSwitchNoFunc : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtContainsFuncDef + (Compiler.CodegenCommon.buildSwitch irContract.functions none none) = + false := + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFuncDefs_noFallback_noReceive + irContract.functions hBodies + have hDispatcherNoFunc : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + false := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef, + hSwitchNoFunc] + exact + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNative_ok_of_yulStmtsContainFuncDef_false + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] + hDispatcherNoFunc + +/-- Supported compiler output gives successful native lowering for the +generated dispatcher statement in any switch-id context. This is the mapping +helper variant used by full runtime lowering. -/ +theorem lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_exists_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (reservedNames : List String) (nextSwitchId : Nat) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + ∃ (dispatcher : List EvmYul.Yul.Ast.Stmt) (finalSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames nextSwitchId + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, finalSwitchId) := by + have hBodies : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false := + generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + hCompile hSupported (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) + have hSwitchNoFunc : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtContainsFuncDef + (Compiler.CodegenCommon.buildSwitch irContract.functions none none) = + false := + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFuncDefs_noFallback_noReceive + irContract.functions hBodies + have hDispatcherNoFunc : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + false := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef, + hSwitchNoFunc] + exact + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames nextSwitchId + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] + hDispatcherNoFunc + +/-- Supported compiler output gives successful native lowering for the selected +generated switch-case body. -/ +theorem lowerStmtsNativeWithSwitchIds_selectedSwitchCaseBody_exists_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (reservedNames : List String) (nextSwitchId : Nat) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (finalSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames nextSwitchId + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (bodyNative, finalSwitchId) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames nextSwitchId + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) + (generatedRuntimeSelectedSwitchCaseBodyHasNoFuncDefs_of_compile_ok_supported_safe + hCompile hSupported hFind) + +/-- Supported compiler output gives successful native lowering for the selected +generated user function body. This is the lowering half of the remaining +selector-hit body-semantics bridge; the dispatcher wrapper theorem above covers +`switchCaseBody fn`, while this theorem exposes the direct `fn.body` target. -/ +theorem lowerStmtsNativeWithSwitchIds_selectedFunctionBody_exists_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (reservedNames : List String) (nextSwitchId : Nat) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (finalSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames nextSwitchId fn.body = + .ok (bodyNative, finalSwitchId) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames nextSwitchId fn.body + (generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + hCompile hSupported + (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) + fn (List.mem_of_find?_eq_some hFind)) + +/-- Supported compiler output gives both the bridged-fragment witness and the +successful native lowering for the selected generated user function body. -/ +theorem selectedFunctionBodyBridgedAndLowered_of_compile_ok_supported + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} {tx : IRTransaction} {fn : IRFunction} + (reservedNames : List String) (nextSwitchId : Nat) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body ∧ + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (finalSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames nextSwitchId fn.body = + .ok (bodyNative, finalSwitchId) := by + exact ⟨ + generatedRuntimeSelectedFunctionBodyBridged_of_compile_ok_supported + hCompile hSupported hFind, + lowerStmtsNativeWithSwitchIds_selectedFunctionBody_exists_of_compile_ok_supported + reservedNames nextSwitchId hCompile hSupported hFind⟩ + +/-- Supported compiler output discharges the selected generated user-body +closure facts that are independent of semantic execution: the selected body is +in the bridged fragment, the native body lowerer succeeds in the caller's +switch-id context, and the selected ABI calldata threshold fits in an EVM word. + +This is the compile-derived half of the remaining selected-body result bridge; +the still-missing piece is the generic native simulation theorem that turns the +lowered body execution into the `NativeGeneratedSelectedUserBodyResultBridgeAtFuel` +result surface. -/ +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_closure_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) : + ∀ (fn : IRFunction) (reservedNames : List String) (nextSwitchId : Nat), + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body ∧ + (∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (finalSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames nextSwitchId fn.body = + .ok (bodyNative, finalSwitchId)) ∧ + 4 + fn.params.length * 32 < EvmYul.UInt256.size := by + intro fn reservedNames nextSwitchId hFind + rcases selectedFunctionBodyBridgedAndLowered_of_compile_ok_supported + reservedNames nextSwitchId hcompile hSupported hFind with + ⟨hBridged, hLowered⟩ + exact ⟨hBridged, hLowered, + generatedFunctionCalldataThreshold_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile fn hFind⟩ + +/-- Supported compiler output always lowers to a native generated-runtime +contract. This discharges the executable lowerer from `SupportedSpec + +compile`: supported external bodies contain no nested function definitions, and +the native lowerer is total for such generated dispatcher statements. -/ +theorem lowerRuntimeContractNative_of_compile_ok_supported_exists + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract := by + have hBodies : + ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false := + generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + hCompile hSupported (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) + have hSwitchNoFunc : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtContainsFuncDef + (Compiler.CodegenCommon.buildSwitch irContract.functions none none) = + false := + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFuncDefs_noFallback_noReceive + irContract.functions hBodies + have hDispatcherNoFunc : + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + false := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef, + hSwitchNoFunc] + cases hMapping : irContract.usesMapping + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNative_ok_of_yulStmtsContainFuncDef_false + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] + hDispatcherNoFunc with + ⟨dispatcher, hLowerDispatcher⟩ + refine ⟨nativeContractOfDispatcher dispatcher, ?_⟩ + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hCompile hSupported hMapping] + rw [hLowerDispatcher] + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] + hDispatcherNoFunc with + ⟨dispatcher, nextSwitchId, hLowerDispatcher⟩ + refine ⟨nativeContractOfDispatcherWithMapping dispatcher, ?_⟩ + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hCompile hSupported hMapping] + rw [hLowerDispatcher] + +/-- Successful mapping-helper native lowering for supported compiler output +exposes the concrete generated dispatcher lowering, threaded switch counter, +and produced native contract. -/ +private theorem lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) : + ∃ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) ∧ + nativeContract = nativeContractOfDispatcherWithMapping dispatcher := + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNative_emitYul_mapping_ok_dispatcher_reserved + irContract nativeContract hMapping + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + (model := spec) (selectors := selectors) (hSupported := hSupported) + (ir := irContract) (hcompile := hCompile)) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile) + hLower + +/-- Dispatcher-contract-shell form of +`lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved`. + +This exposes the native contract used by `EvmYul.Yul.callDispatcher` through +the generated-dispatcher-plus-`mappingSlot` shell. -/ +private theorem lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_public_dispatcher_reserved + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) : + ∃ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) ∧ + nativeContract = + nativeGeneratedDispatcherContractWithMappingOf dispatcher := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hCompile hSupported hMapping hLower with + ⟨dispatcher, nextSwitchId, hDispatcher, hContract⟩ + refine ⟨dispatcher, nextSwitchId, hDispatcher, ?_⟩ + simpa [nativeContractOfDispatcherWithMapping, + nativeGeneratedDispatcherContractWithMappingOf] using hContract + +/-- Generated-runtime lowering split for supported compiler output. + +Any successful native lowering of `emitYul irContract.runtimeCode` is one of +the two `callDispatcher` contract shells: helper-free when +`usesMapping = false`, or dispatcher plus native `mappingSlot` helper when +`usesMapping = true`. -/ +private theorem lowerRuntimeContractNative_of_compile_ok_supported_ok_public_dispatcher_cases + {spec : CompilationModel.CompilationModel} {selectors : List Nat} + {irContract : IRContract} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) : + (irContract.usesMapping = false ∧ + ∃ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher ∧ + nativeContract = nativeGeneratedDispatcherContractOf dispatcher) ∨ + (irContract.usesMapping = true ∧ + ∃ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) ∧ + nativeContract = + nativeGeneratedDispatcherContractWithMappingOf dispatcher) := by + cases hMapping : irContract.usesMapping + · left + exact ⟨rfl, + lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_public_dispatcher + hCompile hSupported hMapping hLower⟩ + · right + exact ⟨rfl, + lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_public_dispatcher_reserved + hCompile hSupported hMapping hLower⟩ + +/-- No-mapping generated dispatcher composition for the direct `callDispatcher` +result. The full runtime native-lowering premise is rebuilt from the concrete +single-dispatcher lowering. -/ +private theorem compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher dispatcher)) := by + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher dispatcher) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_environment + model selectors hSupported irContract tx initialWorld observableSlots + (nativeContractOfDispatcher dispatcher) htxNormalized hcalldataSizeFits + hcompile hLowerRuntime hChainId hBlobBaseFee hNoHeader + (by + simpa [nativeRuntimeFuel, nativeRuntimeDispatcherFuel] using hNativeIR) + +/-- No-mapping generated dispatcher composition under the EVMYulLean global +default environment. -/ +private theorem compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher dispatcher)) := by + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher dispatcher) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_globalDefaults + model selectors hSupported irContract tx initialWorld observableSlots + (nativeContractOfDispatcher dispatcher) htxNormalized hcalldataSizeFits + hcompile hLowerRuntime hChainId hBlobBaseFee hNoHeader + (by + simpa [nativeRuntimeFuel, nativeRuntimeDispatcherFuel] using hNativeIR) + +/-- Mapping-helper generated dispatcher composition for the direct +`callDispatcher` result. The full runtime native-lowering premise is rebuilt +from the concrete dispatcher lowering threaded through the emitted-runtime +reserved-name context. -/ +private theorem compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) := by + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping dispatcher) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_environment + model selectors hSupported irContract tx initialWorld observableSlots + (nativeContractOfDispatcherWithMapping dispatcher) htxNormalized + hcalldataSizeFits hcompile hLowerRuntime hChainId hBlobBaseFee hNoHeader + (by + simpa [nativeRuntimeFuel, nativeRuntimeDispatcherFuel] using hNativeIR) + +/-- Mapping-helper generated dispatcher composition under the EVMYulLean global +default environment. -/ +private theorem compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) := by + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping dispatcher) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_globalDefaults + model selectors hSupported irContract tx initialWorld observableSlots + (nativeContractOfDispatcherWithMapping dispatcher) htxNormalized + hcalldataSizeFits hcompile hLowerRuntime hChainId hBlobBaseFee hNoHeader + (by + simpa [nativeRuntimeFuel, nativeRuntimeDispatcherFuel] using hNativeIR) + +private theorem lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + (funcs : List IRFunction) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (h : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok dispatcher) : + ∃ inner, dispatcher = [.Block inner] ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner] := by + let selectorExpr := Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]] + let defaultCase := Compiler.CodegenCommon.defaultDispatchCase none none + let cases := funcs.map (fun fn => + (fn.selector, + Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" + (Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: fn.body))) + let stmts := + [Yul.YulStmt.let_ "__has_selector" + (Yul.YulExpr.call "iszero" + [Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit 4]]), + Yul.YulStmt.if_ + (Yul.YulExpr.call "iszero" [Yul.YulExpr.ident "__has_selector"]) + defaultCase, + Yul.YulStmt.if_ (Yul.YulExpr.ident "__has_selector") + [Yul.YulStmt.switch selectorExpr cases (some defaultCase)]] + have hBuild : + Compiler.CodegenCommon.buildSwitch funcs none none = + Yul.YulStmt.block stmts := by + simp [Compiler.CodegenCommon.buildSwitch, selectorExpr, defaultCase, cases, + stmts] + rw [hBuild] at h + unfold Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative at h + dsimp at h + rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons] + at h + rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_block] + at h + cases hInner : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + [Yul.YulStmt.block stmts]) + 0 stmts with + | error err => + rw [hInner] at h + simp only [Bind.bind, Except.bind, reduceCtorEq] at h + | ok pair => + cases pair with + | mk inner next => + rw [hInner] at h + simp only [ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + at h + injection h with hEq + subst hEq + refine ⟨inner, rfl, ?_⟩ + rw [hBuild] + unfold Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + dsimp + rw [ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons] + rw [ + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_block] + rw [hInner] + simp only [ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + +private theorem lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + (reservedNames : List String) (nextSwitchId : Nat) + (funcs : List IRFunction) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (h : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames nextSwitchId + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok (dispatcher, finalSwitchId)) : + ∃ inner, dispatcher = [.Block inner] ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames nextSwitchId + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], finalSwitchId) := by + let selectorExpr := Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]] + let defaultCase := Compiler.CodegenCommon.defaultDispatchCase none none + let cases := funcs.map (fun fn => + (fn.selector, + Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" + (Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: fn.body))) + let stmts := + [Yul.YulStmt.let_ "__has_selector" + (Yul.YulExpr.call "iszero" + [Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit 4]]), + Yul.YulStmt.if_ + (Yul.YulExpr.call "iszero" [Yul.YulExpr.ident "__has_selector"]) + defaultCase, + Yul.YulStmt.if_ (Yul.YulExpr.ident "__has_selector") + [Yul.YulStmt.switch selectorExpr cases (some defaultCase)]] + have hBuild : + Compiler.CodegenCommon.buildSwitch funcs none none = + Yul.YulStmt.block stmts := by + simp [Compiler.CodegenCommon.buildSwitch, selectorExpr, defaultCase, cases, + stmts] + rw [hBuild] at h + rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons] + at h + rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_block] + at h + cases hInner : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames nextSwitchId stmts with + | error err => + rw [hInner] at h + simp only [Bind.bind, Except.bind, reduceCtorEq] at h + | ok pair => + cases pair with + | mk inner midSwitchId => + rw [hInner] at h + simp only [ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil, + Except.ok.injEq, Prod.mk.injEq] at h + rcases h with ⟨hDispatcher, hFinal⟩ + subst hDispatcher + subst hFinal + refine ⟨inner, rfl, ?_⟩ + rw [hBuild] + rw [ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons] + rw [ + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_block] + rw [hInner] + simp only [ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_match + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hExternalBodies : ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef fn.body = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots nativeContract) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_positive_match + (generatedRuntimePrefixFunctionNamesUnique_of_compile_ok_supported + hCompile hSupported) + (generatedRuntimeInternalsAreFuncDefs_of_compile_ok_supported + hCompile hSupported) + hExternalBodies + (generatedRuntimeInternalBodiesHaveNoFuncDefs_of_compile_ok_supported + hCompile hSupported) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile) + hLower hEnv hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state observableSlots nativeContract) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_match + hCompile hSupported + (generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + hCompile hSupported hStaticParams hSafeBodies) + hLower hEnv hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state observableSlots nativeContract) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure + hCompile hSupported (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) hLower hEnv hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state observableSlots nativeContract) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure + hCompile hSupported hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +/-- Supported compiler-produced positive dispatcher theorem with +`YulTransaction.ofIR` environment validation discharged from the EVMYulLean +global default environment. -/ +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state observableSlots nativeContract) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure + hCompile hSupported hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_eq_match + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hExternalBodies : ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef fn.body = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_project_eq_match + (generatedRuntimePrefixFunctionNamesUnique_of_compile_ok_supported + hCompile hSupported) + (generatedRuntimeInternalsAreFuncDefs_of_compile_ok_supported + hCompile hSupported) + hExternalBodies + (generatedRuntimeInternalBodiesHaveNoFuncDefs_of_compile_ok_supported + hCompile hSupported) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + spec selectors hSupported irContract hCompile) + (Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + spec selectors hSupported irContract hCompile) + hLower hEnv hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_eq_match + hCompile hSupported + (generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + hCompile hSupported hStaticParams hSafeBodies) + hLower hEnv hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_supported + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure + hCompile hSupported (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) hLower hEnv hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + apply nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure + hCompile hSupported hStaticParams hSafeBodies + · rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hCompile hSupported hNoMapping, hLowerDispatcher] + · exact hEnv + · exact hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + apply nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure + hCompile hSupported hStaticParams hSafeBodies + · rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hCompile hSupported hNoMapping, hLowerDispatcher] + · exact hEnv + · exact hProject + · exact hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + apply nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure + hCompile hSupported hStaticParams hSafeBodies + · rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hCompile hSupported hMapping, hLowerDispatcher] + · exact hEnv + · exact hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + apply nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure + hCompile hSupported hStaticParams hSafeBodies + · rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hCompile hSupported hMapping, hLowerDispatcher] + · exact hEnv + · exact hProject + · exact hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping + hCompile hSupported hNoMapping + (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) + hLowerDispatcher hEnv hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping + hCompile hSupported hNoMapping + (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) + hLowerDispatcher hEnv hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved + hCompile hSupported hMapping + (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) + hLowerDispatcher hEnv hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved + hCompile hSupported hMapping + (generatedRuntimeStaticScalarParams_of_supported hSupported) + (generatedRuntimeSafeBodies_of_supported hSupported) + hLowerDispatcher hEnv hProject hMatch + +/-- No-mapping variant that starts from successful full runtime lowering and +then exposes the generated dispatcher lowering internally. -/ +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hCompile hSupported hNoMapping hLower with + ⟨dispatcher, hLowerDispatcher, _hNativeContract⟩ + exact nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + hEnv (hMatch dispatcher hLowerDispatcher) + +/-- No-mapping projected-result variant that starts from successful full runtime +lowering and then exposes the generated dispatcher lowering internally. -/ +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hCompile hSupported hNoMapping hLower with + ⟨dispatcher, hLowerDispatcher, _hNativeContract⟩ + exact nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + hEnv (hProject dispatcher hLowerDispatcher) hMatch + +/-- Mapping-helper variant that starts from successful full runtime lowering +and then exposes the generated dispatcher lowering under the emitted runtime's +reserved-name context internally. -/ +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hCompile hSupported hMapping hLower with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, _hNativeContract⟩ + exact nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + hEnv (hMatch dispatcher nextSwitchId hLowerDispatcher) + +/-- Mapping-helper projected-result variant that starts from successful full +runtime lowering and then exposes the generated dispatcher lowering under the +emitted runtime's reserved-name context internally. -/ +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hCompile hSupported hMapping hLower with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, _hNativeContract⟩ + exact nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + hEnv (hProject dispatcher nextSwitchId hLowerDispatcher) hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hCompile hSupported hNoMapping hLower with + ⟨dispatcher, hLowerDispatcher, _hNativeContract⟩ + exact nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping + hCompile hSupported hNoMapping hLowerDispatcher hEnv + (hMatch dispatcher hLowerDispatcher) + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hCompile hSupported hNoMapping hLower with + ⟨dispatcher, hLowerDispatcher, _hNativeContract⟩ + exact nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping + hCompile hSupported hNoMapping hLowerDispatcher hEnv + (hProject dispatcher hLowerDispatcher) hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hMatch : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hCompile hSupported hMapping hLower with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, _hNativeContract⟩ + exact nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved + hCompile hSupported hMapping hLowerDispatcher hEnv + (hMatch dispatcher nextSwitchId hLowerDispatcher) + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hCompile hSupported hMapping hLower with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, _hNativeContract⟩ + exact nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved + hCompile hSupported hMapping hLowerDispatcher hEnv + (hProject dispatcher nextSwitchId hLowerDispatcher) hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping + hCompile hSupported hNoMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping + hCompile hSupported hNoMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping + hCompile hSupported hNoMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping + hCompile hSupported hNoMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved + hCompile hSupported hMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved + hCompile hSupported hMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved + hCompile hSupported hMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved + hCompile hSupported hMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping + hCompile hSupported hNoMapping hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping + hCompile hSupported hNoMapping hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping + hCompile hSupported hNoMapping hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping + hCompile hSupported hNoMapping hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved + hCompile hSupported hMapping hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : nativeDispatcherExecMatchesIRPositive fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved + hCompile hSupported hMapping hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hMatch + +/-- Direct generated `callDispatcher` source theorem for no-mapping supported +compiler output from the concrete positive native dispatcher simulation. This +avoids exposing the older `nativeGenerated*MatchesIROn` predicates. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_positive_noMapping_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : + nativeDispatcherExecMatchesIRPositive (nativeRuntimeDispatcherFuel irContract) + irContract tx (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher dispatcher)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher dispatcher)) := by + have hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + simpa [nativeIRRuntimeMatchesIR, nativeRuntimeFuel, + nativeRuntimeDispatcherFuel] using + (nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_environment + (fuel' := nativeRuntimeDispatcherFuel irContract) + (hCompile := hcompile) (hSupported := hSupported) + (hNoMapping := hNoMapping) (hLowerDispatcher := hLowerDispatcher) + (hChainId := hChainId) (hBlobBaseFee := hBlobBaseFee) + (hNoHeader := hNoHeader) hMatch) + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_environment + model selectors hSupported irContract tx initialWorld observableSlots + dispatcher htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hChainId hBlobBaseFee hNoHeader hNativeIR + +/-- Direct generated `callDispatcher` source theorem for no-mapping supported +compiler output under the EVMYulLean global default environment. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_positive_noMapping_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : + nativeDispatcherExecMatchesIRPositive (nativeRuntimeDispatcherFuel irContract) + irContract tx (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher dispatcher)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher dispatcher)) := by + have hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + simpa [nativeIRRuntimeMatchesIR, nativeRuntimeFuel, + nativeRuntimeDispatcherFuel] using + (nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_globalDefaults + (fuel' := nativeRuntimeDispatcherFuel irContract) + (hCompile := hcompile) (hSupported := hSupported) + (hNoMapping := hNoMapping) (hLowerDispatcher := hLowerDispatcher) + (hChainId := hChainId) (hBlobBaseFee := hBlobBaseFee) + (hNoHeader := hNoHeader) hMatch) + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_globalDefaults + model selectors hSupported irContract tx initialWorld observableSlots + dispatcher htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hChainId hBlobBaseFee hNoHeader hNativeIR + +/-- Direct generated `callDispatcher` source theorem for mapping-helper +supported compiler output from the concrete positive native dispatcher +simulation. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_positive_mapping_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : + nativeDispatcherExecMatchesIRPositive (nativeRuntimeDispatcherFuel irContract) + irContract tx (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) := by + have hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + simpa [nativeIRRuntimeMatchesIR, nativeRuntimeFuel, + nativeRuntimeDispatcherFuel] using + (nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_environment + (fuel' := nativeRuntimeDispatcherFuel irContract) + (hCompile := hcompile) (hSupported := hSupported) + (hMapping := hMapping) (hLowerDispatcher := hLowerDispatcher) + (hChainId := hChainId) (hBlobBaseFee := hBlobBaseFee) + (hNoHeader := hNoHeader) hMatch) + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_environment + model selectors hSupported irContract tx initialWorld observableSlots + dispatcher nextSwitchId htxNormalized hcalldataSizeFits hcompile hMapping + hLowerDispatcher hChainId hBlobBaseFee hNoHeader hNativeIR + +/-- Direct generated `callDispatcher` source theorem for mapping-helper +supported compiler output under the EVMYulLean global default environment. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_positive_mapping_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hMatch : + nativeDispatcherExecMatchesIRPositive (nativeRuntimeDispatcherFuel irContract) + irContract tx (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) := by + have hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + simpa [nativeIRRuntimeMatchesIR, nativeRuntimeFuel, + nativeRuntimeDispatcherFuel] using + (nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_globalDefaults + (fuel' := nativeRuntimeDispatcherFuel irContract) + (hCompile := hcompile) (hSupported := hSupported) + (hMapping := hMapping) (hLowerDispatcher := hLowerDispatcher) + (hChainId := hChainId) (hBlobBaseFee := hBlobBaseFee) + (hNoHeader := hNoHeader) hMatch) + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_globalDefaults + model selectors hSupported irContract tx initialWorld observableSlots + dispatcher nextSwitchId htxNormalized hcalldataSizeFits hcompile hMapping + hLowerDispatcher hChainId hBlobBaseFee hNoHeader hNativeIR + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved + hCompile hSupported hMapping hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {dispatcher : List EvmYul.Yul.Ast.Stmt} {nextSwitchId : Nat} + {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved + hCompile hSupported hMapping hLowerDispatcher + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +/-- Direct generated `callDispatcher` source theorem for no-mapping supported +compiler output from a projected native dispatcher result. This avoids exposing +the older `nativeGenerated*MatchesIROn` predicates. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_project_noMapping_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : + nativeProjectedDispatcherResultEq (nativeRuntimeDispatcherFuel irContract) + irContract tx (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher dispatcher)) := by + have hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + simpa [nativeIRRuntimeMatchesIR, nativeRuntimeFuel, + nativeRuntimeDispatcherFuel] using + (nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_environment + (fuel' := nativeRuntimeDispatcherFuel irContract) + (hCompile := hcompile) (hSupported := hSupported) + (hNoMapping := hNoMapping) (hLowerDispatcher := hLowerDispatcher) + (hChainId := hChainId) (hBlobBaseFee := hBlobBaseFee) + (hNoHeader := hNoHeader) hProject hMatch) + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_environment + model selectors hSupported irContract tx initialWorld observableSlots + dispatcher htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hChainId hBlobBaseFee hNoHeader hNativeIR + +/-- Direct generated `callDispatcher` source theorem for no-mapping supported +compiler output from a projected native dispatcher result under the EVMYulLean +global default environment. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_project_noMapping_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : + nativeProjectedDispatcherResultEq (nativeRuntimeDispatcherFuel irContract) + irContract tx (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher dispatcher)) := by + have hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + simpa [nativeIRRuntimeMatchesIR, nativeRuntimeFuel, + nativeRuntimeDispatcherFuel] using + (nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_globalDefaults + (fuel' := nativeRuntimeDispatcherFuel irContract) + (hCompile := hcompile) (hSupported := hSupported) + (hNoMapping := hNoMapping) (hLowerDispatcher := hLowerDispatcher) + (hChainId := hChainId) (hBlobBaseFee := hBlobBaseFee) + (hNoHeader := hNoHeader) hProject hMatch) + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_globalDefaults + model selectors hSupported irContract tx initialWorld observableSlots + dispatcher htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hChainId hBlobBaseFee hNoHeader hNativeIR + +/-- Direct generated `callDispatcher` source theorem for mapping-helper +supported compiler output from a projected native dispatcher result. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_project_mapping_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : + nativeProjectedDispatcherResultEq (nativeRuntimeDispatcherFuel irContract) + irContract tx (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) := by + have hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + simpa [nativeIRRuntimeMatchesIR, nativeRuntimeFuel, + nativeRuntimeDispatcherFuel] using + (nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_environment + (fuel' := nativeRuntimeDispatcherFuel irContract) + (hCompile := hcompile) (hSupported := hSupported) + (hMapping := hMapping) (hLowerDispatcher := hLowerDispatcher) + (hChainId := hChainId) (hBlobBaseFee := hBlobBaseFee) + (hNoHeader := hNoHeader) hProject hMatch) + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_environment + model selectors hSupported irContract tx initialWorld observableSlots + dispatcher nextSwitchId htxNormalized hcalldataSizeFits hcompile hMapping + hLowerDispatcher hChainId hBlobBaseFee hNoHeader hNativeIR + +/-- Direct generated `callDispatcher` source theorem for mapping-helper +supported compiler output from a projected native dispatcher result under the +EVMYulLean global default environment. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_project_mapping_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : + nativeProjectedDispatcherResultEq (nativeRuntimeDispatcherFuel irContract) + irContract tx (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) := by + have hNativeIR : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + simpa [nativeIRRuntimeMatchesIR, nativeRuntimeFuel, + nativeRuntimeDispatcherFuel] using + (nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_globalDefaults + (fuel' := nativeRuntimeDispatcherFuel irContract) + (hCompile := hcompile) (hSupported := hSupported) + (hMapping := hMapping) (hLowerDispatcher := hLowerDispatcher) + (hChainId := hChainId) (hBlobBaseFee := hBlobBaseFee) + (hNoHeader := hNoHeader) hProject hMatch) + exact + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_globalDefaults + model selectors hSupported irContract tx initialWorld observableSlots + dispatcher nextSwitchId htxNormalized hcalldataSizeFits hcompile hMapping + hLowerDispatcher hChainId hBlobBaseFee hNoHeader hNativeIR + +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_environment + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure + hCompile hSupported hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +/-- Supported compiler-produced projected-result theorem with +`YulTransaction.ofIR` environment validation discharged from the EVMYulLean +global default environment. -/ +private theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_globalDefaults + {fuel' : Nat} {spec : CompilationModel.CompilationModel} + {selectors : List Nat} {irContract : IRContract} + {tx : IRTransaction} {state : IRState} {observableSlots : List Nat} + {nativeContract : EvmYul.Yul.Ast.YulContract} {nativeYul : YulResult} + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx state + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok nativeYul)) : + nativeIRRuntimeMatchesIR (Nat.succ fuel') irContract tx state observableSlots := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure + hCompile hSupported hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +/-- Compiler-produced Layer 3 native theorem with an already-closed external +native body-shape witness. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_positive_external_bodies_match + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hExternalBodies : ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots nativeContract) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_match + hCompile hSupported hExternalBodies hLower hEnv hNativeDispatcherExec + +/-- Compiler-produced Layer 3 native theorem from a projected native result, +with an already-closed external native body-shape witness. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_external_bodies_match + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hExternalBodies : ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_eq_match + hCompile hSupported hExternalBodies hLower hEnv hProject hMatch + +/-- Compiler-produced Layer 3 native theorem using source-level safe-body and +static-parameter closure to discharge emitted external body shape. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_positive_body_closure + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots nativeContract) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_positive_external_bodies_match + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported + (generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + hCompile hSupported hStaticParams hSafeBodies) + hLower hEnv hNativeDispatcherExec + +/-- Compiler-produced Layer 3 native theorem from a projected native result, +using source-level safe-body and static-parameter closure. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_body_closure + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_external_bodies_match + fuel' spec selectors irContract tx initialState observableSlots nativeContract nativeYul + hCompile hSupported + (generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + hCompile hSupported hStaticParams hSafeBodies) + hLower hEnv hProject hMatch + +/-- Compiler-produced Layer 3 native theorem for no-mapping dispatcher-statement +lowering, with `YulTransaction.ofIR` environment validation discharged from +representable environment facts. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hNativeDispatcherExec + +/-- Compiler-produced Layer 3 native theorem for no-mapping dispatcher-statement +lowering, with `YulTransaction.ofIR` environment validation discharged from +the EVMYulLean global default environment. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hNativeDispatcherExec + +/-- Compiler-produced Layer 3 native theorem from a projected native result for +no-mapping dispatcher-statement lowering, with `YulTransaction.ofIR` +environment validation discharged from representable environment facts. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hProject hMatch + +/-- Compiler-produced Layer 3 native theorem from a projected native result for +no-mapping dispatcher-statement lowering, with `YulTransaction.ofIR` +environment validation discharged from the EVMYulLean global default +environment. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hProject hMatch + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hNativeDispatcherExec + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hNativeDispatcherExec + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hProject hMatch + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hProject hMatch + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_environment + hCompile hSupported hNoMapping hLowerDispatcher hChainId hBlobBaseFee + hNoHeader hNativeDispatcherExec + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_globalDefaults + hCompile hSupported hNoMapping hLowerDispatcher hChainId hBlobBaseFee + hNoHeader hNativeDispatcherExec + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_environment + hCompile hSupported hNoMapping hLowerDispatcher hChainId hBlobBaseFee + hNoHeader hProject hMatch + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_globalDefaults + hCompile hSupported hNoMapping hLowerDispatcher hChainId hBlobBaseFee + hNoHeader hProject hMatch + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_environment + hCompile hSupported hMapping hLowerDispatcher hChainId hBlobBaseFee + hNoHeader hNativeDispatcherExec + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_globalDefaults + hCompile hSupported hMapping hLowerDispatcher hChainId hBlobBaseFee + hNoHeader hNativeDispatcherExec + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_environment + hCompile hSupported hMapping hLowerDispatcher hChainId hBlobBaseFee + hNoHeader hProject hMatch + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_globalDefaults + hCompile hSupported hMapping hLowerDispatcher hChainId hBlobBaseFee + hNoHeader hProject hMatch + +/-- Compiler-produced Layer 3 native theorem for no-mapping full runtime +lowering, exposing the concrete dispatcher-statement lowering internally. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLower hEnv + hNativeDispatcherExec + +/-- Compiler-produced Layer 3 native theorem for no-mapping projected full +runtime lowering, exposing the concrete dispatcher-statement lowering +internally. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLower hEnv + hProject hMatch + +/-- Compiler-produced Layer 3 native theorem for mapping-helper full runtime +lowering, exposing the concrete reserved dispatcher-statement lowering +internally. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved + hCompile hSupported hMapping hStaticParams hSafeBodies hLower hEnv + hNativeDispatcherExec + +/-- Compiler-produced Layer 3 native theorem for mapping-helper projected full +runtime lowering, exposing the concrete reserved dispatcher-statement lowering +internally. -/ +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved + hCompile hSupported hMapping hStaticParams hSafeBodies hLower hEnv + hProject hMatch + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping + hCompile hSupported hNoMapping hLower hEnv hNativeDispatcherExec + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping + hCompile hSupported hNoMapping hLower hEnv hProject hMatch + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved + hCompile hSupported hMapping hLower hEnv hNativeDispatcherExec + +private theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved + hCompile hSupported hMapping hLower hEnv hProject hMatch + +/-- Supported compiler-produced direct native theorem with an already-closed +external native body-shape witness. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_external_bodies_match + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hExternalBodies : ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots nativeContract) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_match + hCompile hSupported hExternalBodies hLower hEnv hNativeDispatcherExec + +/-- Supported compiler-produced direct native theorem from a projected native +result with an already-closed external native body-shape witness. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_external_bodies_match + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hExternalBodies : ∀ fn, fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef + fn.body = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_eq_match + hCompile hSupported hExternalBodies hLower hEnv hProject hMatch + +/-- Supported compiler-produced positive dispatcher-exec theorem on the direct +native-vs-IR target. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_match + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots nativeContract) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure + hCompile hSupported hStaticParams hSafeBodies hLower hEnv hNativeDispatcherExec + +/-- Supported no-mapping selector-miss source theorem at the structural +fuel exposed by the generic native selector-miss execution lemma. This is not +the canonical generated-runtime fuel theorem; it discharges the native +dispatcher-match premise for the selector-miss/no-mapping path. -/ +private theorem compile_preserves_native_evmYulLean_selector_miss_noMapping_structural + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 19)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive + fuel irContract tx initialState observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, hLowerCases, hNativeDispatcherExec⟩ + refine ⟨reservedNames, n0, cases', midN, hLowerCases, ?_⟩ + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcher] using hNativeDispatcherExec)) + +/-- Supported no-mapping selector-miss source theorem at canonical generated +runtime fuel. This discharges the native dispatcher-match premise for the +selector-miss/no-mapping path without exposing structural fuel. -/ +private theorem compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_atFuel + (nativeRuntimeDispatcherFuel irContract) irContract tx initialState + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, hLowerCases, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := nativeRuntimeDispatcherFuel irContract) + (spec := model) (selectors := selectors) (irContract := irContract) + (tx := tx) (state := initialState) + (observableSlots := observableSlots) + (nativeContract := nativeContractOfDispatcher [.Block inner]) + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcher] + using hNativeDispatcherExec hFuel)) + +/-- Direct `callDispatcher` no-mapping selector-miss theorem at canonical +generated-runtime fuel. + +This is the direct-entrypoint counterpart of +`compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical`: it +projects the actual `EvmYul.Yul.callDispatcher` result instead of routing +through `interpretIRRuntimeNative`. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_miss_noMapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher [.Block inner])) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_atFuel + (nativeRuntimeDispatcherFuel irContract) irContract tx initialState + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, hLowerCases, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + have hGeneratedMatch : + nativeGeneratedCallDispatcherMatchesIROn irContract tx initialState + observableSlots (nativeContractOfDispatcher [.Block inner]) := by + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcher] using hNativeDispatcherExec hFuel + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := hGeneratedMatch) + +/-- Supported mapping-helper selector-miss source theorem at the structural +fuel exposed by the generic native selector-miss execution lemma. This is the +reserved-name-context companion to +`compile_preserves_native_evmYulLean_selector_miss_noMapping_structural`. -/ +private theorem compile_preserves_native_evmYulLean_selector_miss_mapping_structural + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 19)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_withSwitchIds + fuel reservedNames 0 irContract tx initialState observableSlots inner + nextSwitchId functions hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨switchStart, cases', midN, hLowerCases, hNativeDispatcherExec⟩ + refine ⟨switchStart, cases', midN, ?_, ?_⟩ + · simpa [reservedNames] using hLowerCases + · exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec)) + +/-- Supported mapping-helper selector-miss source theorem at canonical +generated runtime fuel. This is the reserved-context companion to +`compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical`. -/ +private theorem compile_preserves_native_evmYulLean_selector_miss_mapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_withSwitchIds_atFuel + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + initialState observableSlots inner nextSwitchId functions + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, hLowerCases, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping hLowerCases + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := nativeRuntimeDispatcherFuel irContract) + (spec := model) (selectors := selectors) (irContract := irContract) + (tx := tx) (state := initialState) + (observableSlots := observableSlots) + (nativeContract := nativeContractOfDispatcherWithMapping [.Block inner]) + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec hFuel)) + +/-- Direct `callDispatcher` mapping-helper selector-miss theorem at canonical +generated-runtime fuel. + +This mirrors +`compile_preserves_native_evmYulLean_callDispatcher_selector_miss_noMapping_canonical` +under the reserved-name context used when the mapping helper is emitted. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_miss_mapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcherWithMapping [.Block inner])) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_withSwitchIds_atFuel + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + initialState observableSlots inner nextSwitchId functions + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, hLowerCases, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping hLowerCases + have hGeneratedMatch : + nativeGeneratedCallDispatcherMatchesIROn irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping [.Block inner]) := by + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec hFuel + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := hGeneratedMatch) + +/-- Direct `callDispatcher` selector-miss theorem from successful lowering of +the whole emitted runtime. + +This wrapper hides the helper/no-helper runtime split and the generated +dispatcher-exec match target. It only exposes the real runtime lowering result +and the selector-miss hypotheses needed to execute the lowered dispatcher. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_miss_lowered_runtime + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract) := by + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 irContract.functions dispatcher nextSwitchId hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + exact + compile_preserves_native_evmYulLean_callDispatcher_selector_miss_mapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots + inner nextSwitchId htxNormalized hcalldataSizeFits hcompile hMapping + hLowerBlock hFind hSelectorRange hNoWrap hFunctionSelectorsRange + · have hNoMapping : irContract.usesMapping = false := by + exact Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + exact + compile_preserves_native_evmYulLean_callDispatcher_selector_miss_noMapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots + inner htxNormalized hcalldataSizeFits hcompile hNoMapping hLowerBlock + hFind hSelectorRange hNoWrap hFunctionSelectorsRange + +/-- Native-vs-IR selector-miss theorem for a supported generated runtime. + +This is the direct `nativeGeneratedCallDispatcherResultOf` selector-miss case: +successful whole-runtime lowering is decomposed into the generated dispatcher +shape, and the generic native selector-miss execution lemma supplies the +projected native result match. -/ +private theorem nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + have hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := + generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_withSwitchIds_atFuel + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + state observableSlots inner nextSwitchId functions + (by simpa [reservedNames] using hLowerBlock) + hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, hLowerCases, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping hLowerCases + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec hFuel + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_atFuel + (nativeRuntimeDispatcherFuel irContract) irContract tx state + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + hLowerBlock hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, hLowerCases, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcher [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcher] using hNativeDispatcherExec hFuel + +/-- Selector-miss native-vs-IR theorem with native lowering produced from +`SupportedSpec + compile`. -/ +theorem nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_exists_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_exists + hcompile hSupported with + ⟨nativeContract, hLowerRuntime⟩ + exact ⟨nativeContract, hLowerRuntime, + nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots nativeContract + hcompile hLowerRuntime hFind hSelectorRange hSelectorsRange hNoWrap⟩ + +/-- Native-vs-IR selector-hit theorem for the generated non-payable value guard. + +When the selected generated function is non-payable and the transaction value is +nonzero modulo the EVM word modulus, both the generated native dispatcher and +the IR interpreter revert before entering the user body. -/ +private theorem nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hNonzero : tx.msgValue % Compiler.Constants.evmModulus ≠ 0) : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + have hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := + generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange + have hSelector : + tx.functionSelector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus := by + simpa [YulTransaction.ofIR] using + (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + have hIRRevert : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.error EvmYul.Yul.Exception.Revert))) := + nativeResultsMatchOn_projectResult_revert_of_nonpayable_nonzero + irContract tx state observableSlots fn hFind hNonPayable hNonzero + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_callvalue_revert_withSwitchIds_atFuel_projectResult_eq + (nativeRuntimeDispatcherFuel irContract) tx.functionSelector + reservedNames 0 irContract.functions fn inner nextSwitchId functions + tx state.storage state.events + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (by simpa [reservedNames] using hLowerBlock) + hSelector hFind hNoWrap hSelectorRangeNative hFunctionSelectorsRange + hNonPayable hNonzero with + ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, hCont⟩ + have hFuel : + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length_plus24 + hcompile hSupported hMapping hLowerCases + rcases hCont hFuel with ⟨hExec, _hProject⟩ + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeRuntimeDispatcherFuel, nativeContractOfDispatcherWithMapping, + functions, hExec] using hIRRevert + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_callvalue_revert_atFuel_projectResult_eq + (nativeRuntimeDispatcherFuel irContract) tx.functionSelector + irContract.functions fn inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + tx state.storage state.events + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + hLowerBlock hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange hNonPayable hNonzero with + ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, + hUserBodyLower, hCont⟩ + have hFuel : + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length_plus24 + hcompile hSupported hNoMapping hLowerCases + rcases hCont hFuel with ⟨hExec, _hProject⟩ + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcher [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeRuntimeDispatcherFuel, nativeContractOfDispatcher, hExec] + using hIRRevert + +/-- Native-vs-IR selector-hit theorem for the generated calldata-size guard. + +When the selected generated function is value-safe but the transaction calldata +does not contain all selected ABI arguments, both the generated native +dispatcher and the IR interpreter revert before entering the user body. -/ +private theorem nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hguards : DispatchGuardsSafe fn tx) + (hValue : + fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + have hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := + generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange + have hSelector : + tx.functionSelector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus := by + simpa [YulTransaction.ofIR] using + (Nat.mod_eq_of_lt hSelectorRange).symm + have hSelectorRangeNative : tx.functionSelector < EvmYul.UInt256.size := by + exact Nat.lt_trans hSelectorRange (by decide) + have hIRRevert : + nativeResultsMatchOn observableSlots (interpretIR irContract tx state) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.error EvmYul.Yul.Exception.Revert))) := + nativeResultsMatchOn_projectResult_revert_of_args_short + irContract tx state observableSlots fn hFind hValue hArgsShort + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + by_cases hPayable : fn.payable = true + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_payable_args_short_revert_withSwitchIds_atFuel_projectResult_eq + (nativeRuntimeDispatcherFuel irContract) tx.functionSelector + reservedNames 0 irContract.functions fn inner nextSwitchId functions + tx state.storage state.events + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (by simpa [reservedNames] using hLowerBlock) + hSelector hFind hNoWrap hSelectorRangeNative hFunctionSelectorsRange + hPayable hguards hArgsShort with + ⟨_switchStart, cases', _midN, _body', _bodyNative, _bodyStart, + _bodyEnd, _userBodyStart, hLowerCases, _hCase, _hBodyLower, + _hUserBodyLower, hCont⟩ + have hFuel24 : + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length_plus24 + hcompile hSupported hMapping hLowerCases + have hFuel23 : + cases'.length + 23 ≤ nativeRuntimeDispatcherFuel irContract := by + omega + rcases hCont hFuel23 with ⟨hExec, _hProject⟩ + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeRuntimeDispatcherFuel, nativeContractOfDispatcherWithMapping, + functions, hExec] using hIRRevert + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + have hZero : tx.msgValue % Compiler.Constants.evmModulus = 0 := by + rcases hValue with hPayable' | hZero + · rw [hNonPayable] at hPayable' + simp at hPayable' + · exact hZero + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_args_short_revert_withSwitchIds_atFuel_projectResult_eq + (nativeRuntimeDispatcherFuel irContract) tx.functionSelector + reservedNames 0 irContract.functions fn inner nextSwitchId functions + tx state.storage state.events + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (by simpa [reservedNames] using hLowerBlock) + hSelector hFind hNoWrap hSelectorRangeNative hFunctionSelectorsRange + hNonPayable hguards hZero hArgsShort with + ⟨_switchStart, cases', _midN, _body', _bodyNative, _bodyStart, + _bodyEnd, _userBodyStart, hLowerCases, _hCase, _hBodyLower, + _hUserBodyLower, hCont⟩ + have hFuel : + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length_plus24 + hcompile hSupported hMapping hLowerCases + rcases hCont hFuel with ⟨hExec, _hProject⟩ + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeRuntimeDispatcherFuel, nativeContractOfDispatcherWithMapping, + functions, hExec] using hIRRevert + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + by_cases hPayable : fn.payable = true + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_payable_args_short_revert_atFuel_projectResult_eq + (nativeRuntimeDispatcherFuel irContract) tx.functionSelector + irContract.functions fn inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + tx state.storage state.events + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + hLowerBlock hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange hPayable hguards hArgsShort with + ⟨_reservedNames, _n0, cases', _midN, _body', _bodyNative, + _bodyStart, _bodyEnd, _userBodyStart, hLowerCases, _hCase, + _hBodyLower, _hUserBodyLower, hCont⟩ + have hFuel24 : + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length_plus24 + hcompile hSupported hNoMapping hLowerCases + have hFuel23 : + cases'.length + 23 ≤ nativeRuntimeDispatcherFuel irContract := by + omega + rcases hCont hFuel23 with ⟨hExec, _hProject⟩ + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcher [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeRuntimeDispatcherFuel, nativeContractOfDispatcher, hExec] + using hIRRevert + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + have hZero : tx.msgValue % Compiler.Constants.evmModulus = 0 := by + rcases hValue with hPayable' | hZero + · rw [hNonPayable] at hPayable' + simp at hPayable' + · exact hZero + rcases + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_args_short_revert_atFuel_projectResult_eq + (nativeRuntimeDispatcherFuel irContract) tx.functionSelector + irContract.functions fn inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + tx state.storage state.events + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + hLowerBlock hSelector hFind hNoWrap hSelectorRangeNative + hFunctionSelectorsRange hNonPayable hguards hZero hArgsShort with + ⟨_reservedNames, _n0, cases', _midN, _body', _bodyNative, + _bodyStart, _bodyEnd, _userBodyStart, hLowerCases, _hCase, + _hBodyLower, _hUserBodyLower, hCont⟩ + have hFuel : + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length_plus24 + hcompile hSupported hNoMapping hLowerCases + rcases hCont hFuel with ⟨hExec, _hProject⟩ + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcher [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeRuntimeDispatcherFuel, nativeContractOfDispatcher, hExec] + using hIRRevert + +/-- Selector-hit non-payable value-guard revert theorem with native lowering +produced from `SupportedSpec + compile`. -/ +theorem nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_exists_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hNonzero : tx.msgValue % Compiler.Constants.evmModulus ≠ 0) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_exists + hcompile hSupported with + ⟨nativeContract, hLowerRuntime⟩ + exact ⟨nativeContract, hLowerRuntime, + nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots nativeContract + fn hcompile hLowerRuntime hFind hSelectorRange hSelectorsRange hNoWrap + hNonPayable hNonzero⟩ + +/-- Selector-hit calldata-size guard revert theorem with native lowering +produced from `SupportedSpec + compile`. -/ +theorem nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_exists_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hguards : DispatchGuardsSafe fn tx) + (hValue : + fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_exists + hcompile hSupported with + ⟨nativeContract, hLowerRuntime⟩ + exact ⟨nativeContract, hLowerRuntime, + nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots nativeContract + fn hcompile hLowerRuntime hFind hSelectorRange hSelectorsRange hNoWrap + hguards hValue hArgsShort⟩ + +/-- Selector-miss direct `callDispatcher` theorem with generated function +selector ranges derived from the source selector list. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_miss_lowered_runtime_selectors_range + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract) := + compile_preserves_native_evmYulLean_callDispatcher_selector_miss_lowered_runtime + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract htxNormalized hcalldataSizeFits hcompile hLowerRuntime hFind + hSelectorRange hNoWrap + (generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange) + +/-- Selector-miss direct `callDispatcher` theorem deriving calldata no-wrap from +the transaction calldata-size fit premise. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_miss_lowered_runtime_selectors_range_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract) := + compile_preserves_native_evmYulLean_callDispatcher_selector_miss_lowered_runtime_selectors_range + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract htxNormalized hcalldataSizeFits hcompile hLowerRuntime hFind + hSelectorRange hSelectorsRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) + +/-- Selector-miss native runtime theorem deriving generated dispatcher lowering +directly from `SupportedSpec + compile`. + +This is the first fully generated selector-miss composition point: callers no +longer provide the lowered dispatcher or whole-runtime lowering witness. -/ +private theorem compile_preserves_native_evmYulLean_selector_miss_of_compile_ok_supported + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := by + have hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := + generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange + have hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size := + txNoWrap_of_calldataSizeFits hcalldataSizeFits + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_exists_of_compile_ok_supported + reservedNames 0 hcompile hSupported with + ⟨dispatcher, nextSwitchId, hLowerDispatcher⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst dispatcher + exact + compile_preserves_native_evmYulLean_selector_miss_mapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots + inner nextSwitchId htxNormalized hcalldataSizeFits hcompile hMapping + (by simpa [reservedNames] using hLowerBlock) + hFind hSelectorRange hNoWrap hFunctionSelectorsRange hEnv + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_exists_of_compile_ok_supported + hcompile hSupported with + ⟨dispatcher, hLowerDispatcher⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst dispatcher + exact + compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots + inner htxNormalized hcalldataSizeFits hcompile hNoMapping hLowerBlock + hFind hSelectorRange hNoWrap hFunctionSelectorsRange hEnv + +/-- Supported no-mapping selector-hit source theorem at the structural fuel +exposed by the generic native selector-hit success execution lemma. The +selected-body execution, switch-temporary freshness, matched-flag preservation, +final-state projection, and IR/native result match remain explicit premises. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_structural + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 19)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive + fuel irContract tx initialState observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn final nativeYul hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hNativeDispatcherExec⟩ + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hFresh hBody hStmtPreserves hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 19) + irContract tx initialState observableSlots + (nativeContractOfDispatcher [.Block inner]) := by + refine hNativeDispatcherExec ?_ ?_ ?_ hMatch + · simpa [initialState, nativeContractOfDispatcher] using hBody + · intro pre suffix hcases + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' (EvmYul.UInt256.ofNat 1) + (some (nativeContractOfDispatcher [.Block inner])) + (by simpa using hFresh) hCase + (by simpa [nativeContractOfDispatcher] using hStmtPreserves) + · simpa [initialState, nativeContractOfDispatcher] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + hcompile hSupported hLowerRuntime hEnv hNativeDispatcherExec') + +/-- Supported no-mapping selector-hit source theorem for the payable generated +prefix path. The public execution and matched-flag preservation premises are +over the lowered user body `fn.body`, while the generated selector case body is +only exposed as a lowering fact. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_structural_payable_generated_prefix + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 23)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_generated_prefix + fuel irContract tx initialState observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn final nativeYul hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange hPayable hguards hArgs with + ⟨reservedNames, n0, cases', _midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, _hLowerCases, hCase, hBodyLower, hUserBodyLower, + hNativeDispatcherExec⟩ + refine ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 23) + irContract tx initialState observableSlots + (nativeContractOfDispatcher [.Block inner]) := by + refine hNativeDispatcherExec ?_ ?_ ?_ hMatch + · simpa [initialState, nativeContractOfDispatcher] using hBody + · simpa [nativeContractOfDispatcher] using hPreservesMatched + · simpa [initialState, nativeContractOfDispatcher] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + hcompile hSupported hLowerRuntime hEnv hNativeDispatcherExec') + +/-- Supported no-mapping selector-hit source theorem for the non-payable +generated prefix path. The public execution and matched-flag preservation +premises are over the lowered user body `fn.body`. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_structural_nonpayable_generated_prefix + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 24)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_generated_prefix + fuel irContract tx initialState observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn final nativeYul hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange hNonPayable hguards hArgs with + ⟨reservedNames, n0, cases', _midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, _hLowerCases, hCase, hBodyLower, hUserBodyLower, + hNativeDispatcherExec⟩ + refine ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 24) + irContract tx initialState observableSlots + (nativeContractOfDispatcher [.Block inner]) := by + refine hNativeDispatcherExec ?_ ?_ ?_ hMatch + · simpa [initialState, nativeContractOfDispatcher] using hBody + · simpa [nativeContractOfDispatcher] using hPreservesMatched + · simpa [initialState, nativeContractOfDispatcher] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + hcompile hSupported hLowerRuntime hEnv hNativeDispatcherExec') + +/-- Supported no-mapping selector-hit source theorem at canonical generated +runtime fuel for the native selector-hit normal-success path. The selected +native-body execution, switch-temporary freshness, matched-flag preservation, +projection, and IR/native result match remain explicit premises. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_atFuel + (nativeRuntimeDispatcherFuel irContract) irContract tx initialState + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn final nativeYul hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', _midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hFresh hBody hStmtPreserves hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (nativeRuntimeDispatcherFuel irContract) + irContract tx initialState observableSlots + (nativeContractOfDispatcher [.Block inner]) := by + refine hNativeDispatcherExec hFuel ?_ ?_ ?_ hMatch + · simpa [initialState, nativeContractOfDispatcher] using hBody + · intro pre suffix hcases + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' (EvmYul.UInt256.ofNat 1) + (some (nativeContractOfDispatcher [.Block inner])) + (by simpa using hFresh) hCase + (by simpa [nativeContractOfDispatcher] using hStmtPreserves) + · simpa [initialState, nativeContractOfDispatcher] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := nativeRuntimeDispatcherFuel irContract) + (spec := model) (selectors := selectors) (irContract := irContract) + (tx := tx) (state := initialState) + (observableSlots := observableSlots) + (nativeContract := nativeContractOfDispatcher [.Block inner]) + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcher] using hNativeDispatcherExec')) + +/-- Block-preservation variant of +`compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical`. + +This keeps selected-body execution and projection explicit, but replaces the +public switch-temp freshness plus per-statement preservation premises with a +single block-level preservation obligation for the selected native body. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_preserved + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_atFuel + (nativeRuntimeDispatcherFuel irContract) irContract tx initialState + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn final nativeYul hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (nativeRuntimeDispatcherFuel irContract) + irContract tx initialState observableSlots + (nativeContractOfDispatcher [.Block inner]) := by + refine hNativeDispatcherExec hFuel ?_ ?_ ?_ hMatch + · simpa [initialState, nativeContractOfDispatcher] using hBody + · simpa [nativeContractOfDispatcher] using hPreservesMatched + · simpa [initialState, nativeContractOfDispatcher] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := nativeRuntimeDispatcherFuel irContract) + (spec := model) (selectors := selectors) (irContract := irContract) + (tx := tx) (state := initialState) + (observableSlots := observableSlots) + (nativeContract := nativeContractOfDispatcher [.Block inner]) + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcher] using hNativeDispatcherExec')) + +/-- Direct `callDispatcher` no-mapping selector-hit success theorem at +canonical generated-runtime fuel, using the block-preservation obligation for +the selected native body. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_noMapping_canonical_preserved + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher [.Block inner]))) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_atFuel + (nativeRuntimeDispatcherFuel irContract) irContract tx initialState + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn final nativeYul hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + have hGeneratedMatch : + nativeGeneratedCallDispatcherMatchesIROn irContract tx initialState + observableSlots (nativeContractOfDispatcher [.Block inner]) := by + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcher] using + hNativeDispatcherExec hFuel + (by simpa [initialState, nativeContractOfDispatcher] using hBody) + (by simpa [nativeContractOfDispatcher] using hPreservesMatched) + (by simpa [initialState, nativeContractOfDispatcher] using hProject) + hMatch + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := hGeneratedMatch) + +/-- Direct `callDispatcher` no-mapping selector-hit success theorem at +canonical generated-runtime fuel, deriving selected-body block preservation from +native switch freshness and per-statement preservation. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_noMapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher [.Block inner]))) := by + rcases + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_noMapping_canonical_preserved + model selectors hSupported irContract tx initialWorld observableSlots inner + fn final nativeYul htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, hCase, hBodyLower, + hPreserved⟩ + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hFresh hBody hStmtPreserves hProject hMatch + exact hPreserved hBody + (fun pre suffix hcases => + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' (EvmYul.UInt256.ofNat 1) + (some (nativeContractOfDispatcher [.Block inner])) + (by simpa using hFresh) hCase + (by simpa [nativeContractOfDispatcher] using hStmtPreserves)) + hProject hMatch + +/-- Supported mapping-helper selector-hit source theorem at the structural fuel +exposed by the reserved-context native selector-hit success execution lemma. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_mapping_structural + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) stmt + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 19)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds + fuel reservedNames 0 irContract tx initialState observableSlots inner + nextSwitchId functions fn final nativeYul hLowerDispatcher hFind + hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hNativeDispatcherExec⟩ + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro hFresh hBody hStmtPreserves hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 19) + irContract tx initialState observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + refine hNativeDispatcherExec ?_ ?_ ?_ hMatch + · simpa [initialState, reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody + · intro pre suffix hcases + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' (EvmYul.UInt256.ofNat 1) + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (by simpa [reservedNames] using hFresh) hCase + (by + simpa [reservedNames, nativeContractOfDispatcherWithMapping, functions] + using hStmtPreserves) + · simpa [initialState, nativeContractOfDispatcherWithMapping, functions] + using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec')) + +/-- Supported mapping-helper selector-hit source theorem for the payable +generated prefix path. The selected-body execution and matched-flag +preservation premises are over the lowered user body `fn.body`, not over the +generated `switchCaseBody fn` wrapper. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_mapping_structural_payable_generated_prefix + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) userBodyStart fn.body = + .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 23)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_withSwitchIds_generated_prefix + fuel reservedNames 0 irContract tx initialState observableSlots inner + nextSwitchId functions fn final nativeYul hLowerDispatcher hFind + hSelectorRange hNoWrap hFunctionSelectorsRange hPayable hguards hArgs with + ⟨switchStart, cases', _midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, _hLowerCases, hCase, hBodyLower, hUserBodyLower, + hNativeDispatcherExec⟩ + refine ⟨switchStart, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, ?_, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · simpa [reservedNames] using hUserBodyLower + · intro hBody hPreservesMatched hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 23) + irContract tx initialState observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + refine hNativeDispatcherExec ?_ ?_ ?_ hMatch + · simpa [initialState, reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody + · simpa [reservedNames, nativeContractOfDispatcherWithMapping, functions] + using hPreservesMatched + · simpa [initialState, nativeContractOfDispatcherWithMapping, functions] + using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec')) + +/-- Supported mapping-helper selector-hit source theorem for the non-payable +generated prefix path. The selected-body execution and matched-flag +preservation premises are over the lowered user body `fn.body`. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_mapping_structural_nonpayable_generated_prefix + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) userBodyStart fn.body = + .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 24)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_withSwitchIds_generated_prefix + fuel reservedNames 0 irContract tx initialState observableSlots inner + nextSwitchId functions fn final nativeYul hLowerDispatcher hFind + hSelectorRange hNoWrap hFunctionSelectorsRange hNonPayable hguards hArgs with + ⟨switchStart, cases', _midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, _hLowerCases, hCase, hBodyLower, hUserBodyLower, + hNativeDispatcherExec⟩ + refine ⟨switchStart, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, ?_, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · simpa [reservedNames] using hUserBodyLower + · intro hBody hPreservesMatched hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 24) + irContract tx initialState observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + refine hNativeDispatcherExec ?_ ?_ ?_ hMatch + · simpa [initialState, reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody + · simpa [reservedNames, nativeContractOfDispatcherWithMapping, functions] + using hPreservesMatched + · simpa [initialState, nativeContractOfDispatcherWithMapping, functions] + using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec')) + +/-- Lowered-runtime selector-hit source theorem for the payable generated +prefix path. This hides the mapping-helper/no-mapping split while keeping the +selected native execution and preservation obligations on the lowered user body +`fn.body`. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_lowered_runtime_payable_generated_prefix + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 23)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 irContract.functions dispatcher nextSwitchId hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + compile_preserves_native_evmYulLean_selector_hit_ok_mapping_structural_payable_generated_prefix + fuel model selectors hSupported irContract tx initialWorld + observableSlots inner nextSwitchId fn final nativeYul htxNormalized + hcalldataSizeFits hcompile hMapping hLowerBlock hFind hSelectorRange + hNoWrap hFunctionSelectorsRange hPayable hguards hArgs hEnv with + ⟨switchStart, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, hCont⟩ + refine ⟨ + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode, + switchStart, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + exact hCont hBody hPreservesMatched hProject hMatch + · have hNoMapping : irContract.usesMapping = false := by + exact Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_structural_payable_generated_prefix + fuel model selectors hSupported irContract tx initialWorld + observableSlots inner fn final nativeYul htxNormalized + hcalldataSizeFits hcompile hNoMapping hLowerBlock hFind hSelectorRange + hNoWrap hFunctionSelectorsRange hPayable hguards hArgs hEnv with + ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, hCont⟩ + exact ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, hCont⟩ + +/-- Lowered-runtime selector-hit source theorem for the non-payable generated +prefix path. This hides the mapping-helper/no-mapping split while keeping the +selected native execution and preservation obligations on the lowered user body +`fn.body`. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_lowered_runtime_nonpayable_generated_prefix + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 24)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 irContract.functions dispatcher nextSwitchId hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + compile_preserves_native_evmYulLean_selector_hit_ok_mapping_structural_nonpayable_generated_prefix + fuel model selectors hSupported irContract tx initialWorld + observableSlots inner nextSwitchId fn final nativeYul htxNormalized + hcalldataSizeFits hcompile hMapping hLowerBlock hFind hSelectorRange + hNoWrap hFunctionSelectorsRange hNonPayable hguards hArgs hEnv with + ⟨switchStart, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, hCont⟩ + refine ⟨ + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode, + switchStart, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + exact hCont hBody hPreservesMatched hProject hMatch + · have hNoMapping : irContract.usesMapping = false := by + exact Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_structural_nonpayable_generated_prefix + fuel model selectors hSupported irContract tx initialWorld + observableSlots inner fn final nativeYul htxNormalized + hcalldataSizeFits hcompile hNoMapping hLowerBlock hFind hSelectorRange + hNoWrap hFunctionSelectorsRange hNonPayable hguards hArgs hEnv with + ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, hCont⟩ + exact ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, hCont⟩ + +/-- Exact-total-fuel lowered-runtime selector-hit source theorem for the +payable generated prefix path. This hides the mapping-helper/no-mapping split +while stating the native dispatcher result at the externally supplied `fuel'`. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_lowered_runtime_payable_generated_prefix_atFuel + (fuel' : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 23 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_withSwitchIds_generated_prefix_atFuel + fuel' reservedNames 0 irContract tx initialState observableSlots + inner nextSwitchId functions fn final nativeYul hLowerBlock hFind + hSelectorRange hNoWrap hFunctionSelectorsRange hPayable hguards hArgs with + ⟨switchStart, cases', _midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, _hLowerCases, hCase, hBodyLower, hUserBodyLower, + hNativeDispatcherExec⟩ + refine ⟨reservedNames, switchStart, cases', body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hBody hPreservesMatched hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx initialState observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + refine hNativeDispatcherExec hFuel ?_ ?_ ?_ hMatch + · simpa [initialState, reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody + · simpa [reservedNames, nativeContractOfDispatcherWithMapping, functions] + using hPreservesMatched + · simpa [initialState, nativeContractOfDispatcherWithMapping, functions] + using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := fuel') hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec')) + · have hNoMapping : irContract.usesMapping = false := by + exact Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_generated_prefix_atFuel + fuel' irContract tx initialState observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn final nativeYul hLowerBlock hFind hSelectorRange hNoWrap + hFunctionSelectorsRange hPayable hguards hArgs with + ⟨reservedNames, n0, cases', _midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, _hLowerCases, hCase, hBodyLower, hUserBodyLower, + hNativeDispatcherExec⟩ + refine ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hBody hPreservesMatched hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx initialState observableSlots + (nativeContractOfDispatcher [.Block inner]) := by + refine hNativeDispatcherExec hFuel ?_ ?_ ?_ hMatch + · simpa [initialState, nativeContractOfDispatcher] using hBody + · simpa [nativeContractOfDispatcher] using hPreservesMatched + · simpa [initialState, nativeContractOfDispatcher] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := fuel') hcompile hSupported hLowerRuntime hEnv + (by simpa [nativeContractOfDispatcher] using hNativeDispatcherExec')) + +/-- Exact-total-fuel lowered-runtime selector-hit source theorem for the +non-payable generated prefix path. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_lowered_runtime_nonpayable_generated_prefix_atFuel + (fuel' : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 24 ≤ fuel' → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_withSwitchIds_generated_prefix_atFuel + fuel' reservedNames 0 irContract tx initialState observableSlots + inner nextSwitchId functions fn final nativeYul hLowerBlock hFind + hSelectorRange hNoWrap hFunctionSelectorsRange hNonPayable hguards + hArgs with + ⟨switchStart, cases', _midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, _hLowerCases, hCase, hBodyLower, hUserBodyLower, + hNativeDispatcherExec⟩ + refine ⟨reservedNames, switchStart, cases', body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hBody hPreservesMatched hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx initialState observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + refine hNativeDispatcherExec hFuel ?_ ?_ ?_ hMatch + · simpa [initialState, reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody + · simpa [reservedNames, nativeContractOfDispatcherWithMapping, functions] + using hPreservesMatched + · simpa [initialState, nativeContractOfDispatcherWithMapping, functions] + using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := fuel') hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec')) + · have hNoMapping : irContract.usesMapping = false := by + exact Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_generated_prefix_atFuel + fuel' irContract tx initialState observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn final nativeYul hLowerBlock hFind hSelectorRange hNoWrap + hFunctionSelectorsRange hNonPayable hguards hArgs with + ⟨reservedNames, n0, cases', _midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, _hLowerCases, hCase, hBodyLower, hUserBodyLower, + hNativeDispatcherExec⟩ + refine ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hBody hPreservesMatched hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive fuel' + irContract tx initialState observableSlots + (nativeContractOfDispatcher [.Block inner]) := by + refine hNativeDispatcherExec hFuel ?_ ?_ ?_ hMatch + · simpa [initialState, nativeContractOfDispatcher] using hBody + · simpa [nativeContractOfDispatcher] using hPreservesMatched + · simpa [initialState, nativeContractOfDispatcher] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := fuel') hcompile hSupported hLowerRuntime hEnv + (by simpa [nativeContractOfDispatcher] using hNativeDispatcherExec')) + +/-- Supported mapping-helper selector-hit source theorem at canonical generated +runtime fuel for the native selector-hit normal-success path. This is the +reserved-context companion to +`compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical`. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) stmt + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds_atFuel + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + initialState observableSlots inner nextSwitchId functions fn final nativeYul + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping + (by simpa [reservedNames] using hLowerCases) + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro hFresh hBody hStmtPreserves hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (nativeRuntimeDispatcherFuel irContract) + irContract tx initialState observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + refine hNativeDispatcherExec hFuel ?_ ?_ ?_ hMatch + · simpa [initialState, reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody + · intro pre suffix hcases + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' (EvmYul.UInt256.ofNat 1) + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (by simpa [reservedNames] using hFresh) hCase + (by + simpa [reservedNames, nativeContractOfDispatcherWithMapping, functions] + using hStmtPreserves) + · simpa [initialState, nativeContractOfDispatcherWithMapping, functions] + using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := nativeRuntimeDispatcherFuel irContract) + (spec := model) (selectors := selectors) (irContract := irContract) + (tx := tx) (state := initialState) + (observableSlots := observableSlots) + (nativeContract := nativeContractOfDispatcherWithMapping [.Block inner]) + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec')) + +/-- Supported no-mapping selector-hit source theorem at the structural fuel +exposed by the generic native selector-hit error execution lemma. The selected +native-body error/halt projection and IR/native result match remain explicit +premises. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_error_noMapping_structural + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 19)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive + fuel irContract tx initialState observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn err nativeYul hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hNativeDispatcherExec⟩ + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hBody hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 19) + irContract tx initialState observableSlots + (nativeContractOfDispatcher [.Block inner]) := by + refine hNativeDispatcherExec ?_ ?_ hMatch + · simpa [initialState, nativeContractOfDispatcher] using hBody + · simpa [initialState] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + hcompile hSupported hLowerRuntime hEnv hNativeDispatcherExec') + +/-- Supported no-mapping selector-hit source theorem at canonical generated +runtime fuel for the native selector-hit error/halt path. The selected native +body error/halt projection and IR/native result match remain explicit +premises. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcher [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_noMapping + hcompile hSupported hNoMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_atFuel + (nativeRuntimeDispatcherFuel irContract) irContract tx initialState + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn err nativeYul hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hBody hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (nativeRuntimeDispatcherFuel irContract) + irContract tx initialState observableSlots + (nativeContractOfDispatcher [.Block inner]) := by + refine hNativeDispatcherExec hFuel ?_ ?_ hMatch + · simpa [initialState, nativeContractOfDispatcher] using hBody + · simpa [initialState] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := nativeRuntimeDispatcherFuel irContract) + (spec := model) (selectors := selectors) (irContract := irContract) + (tx := tx) (state := initialState) + (observableSlots := observableSlots) + (nativeContract := nativeContractOfDispatcher [.Block inner]) + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcher] using hNativeDispatcherExec')) + +/-- Direct `callDispatcher` no-mapping selector-hit error theorem at canonical +generated-runtime fuel. + +The selected-body error execution, projection, and IR/native result match remain +explicit, but the conclusion is the projected native `EvmYul.Yul.callDispatcher` +result. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_noMapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeContractOfDispatcher [.Block inner]))) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_atFuel + (nativeRuntimeDispatcherFuel irContract) irContract tx initialState + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn err nativeYul hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hBody hProject hMatch + have hGeneratedMatch : + nativeGeneratedCallDispatcherMatchesIROn irContract tx initialState + observableSlots (nativeContractOfDispatcher [.Block inner]) := by + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcher] using + hNativeDispatcherExec hFuel + (by simpa [initialState, nativeContractOfDispatcher] using hBody) + (by simpa [initialState] using hProject) + hMatch + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := hGeneratedMatch) + +/-- Supported mapping-helper selector-hit source theorem at the structural fuel +exposed by the reserved-context native selector-hit error execution lemma. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_error_mapping_structural + (fuel : Nat) + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (fuel + cases'.length + 19)) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds + fuel reservedNames 0 irContract tx initialState observableSlots inner + nextSwitchId functions fn err nativeYul hLowerDispatcher hFind + hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hNativeDispatcherExec⟩ + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro hBody hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (fuel + cases'.length + 19) + irContract tx initialState observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + refine hNativeDispatcherExec ?_ ?_ hMatch + · simpa [initialState, reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody + · simpa [initialState] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec')) + +/-- Supported mapping-helper selector-hit source theorem at canonical generated +runtime fuel for the native selector-hit error/halt path. This is the +reserved-context companion to +`compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical`. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds_atFuel + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + initialState observableSlots inner nextSwitchId functions fn err nativeYul + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping + (by simpa [reservedNames] using hLowerCases) + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro hBody hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (nativeRuntimeDispatcherFuel irContract) + irContract tx initialState observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + refine hNativeDispatcherExec hFuel ?_ ?_ hMatch + · simpa [initialState, reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody + · simpa [initialState] using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := nativeRuntimeDispatcherFuel irContract) + (spec := model) (selectors := selectors) (irContract := irContract) + (tx := tx) (state := initialState) + (observableSlots := observableSlots) + (nativeContract := nativeContractOfDispatcherWithMapping [.Block inner]) + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec')) + +/-- Direct `callDispatcher` mapping selector-hit error theorem at canonical +generated-runtime fuel. + +The selected-body error execution, projection, and IR/native result match remain +explicit, but the conclusion is the projected native `EvmYul.Yul.callDispatcher` +result for the generated runtime with the native mapping helper installed. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_mapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]))) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds_atFuel + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + initialState observableSlots inner nextSwitchId functions fn err nativeYul + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping + (by simpa [reservedNames] using hLowerCases) + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro hBody hProject hMatch + have hGeneratedMatch : + nativeGeneratedCallDispatcherMatchesIROn irContract tx initialState + observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcherWithMapping, functions] using + hNativeDispatcherExec hFuel + (by simpa [initialState, reservedNames, + nativeContractOfDispatcherWithMapping, functions] using hBody) + (by simpa [initialState] using hProject) + hMatch + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := hGeneratedMatch) + +/-- Direct `callDispatcher` selector-hit error theorem from successful +lowering of the whole emitted runtime. + +The selected-body error execution, projection, and IR/native result match remain +the semantic obligations, but the emitted-runtime mapping split and concrete +dispatcher lowering are internal to this wrapper. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract)) := by + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 irContract.functions dispatcher nextSwitchId hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_mapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots + inner nextSwitchId fn err nativeYul htxNormalized hcalldataSizeFits + hcompile hMapping hLowerBlock hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + refine ⟨ + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode, + switchStart, cases', body', bodyStart, bodyEnd, hCase, hBodyLower, ?_⟩ + intro hBody hProject hMatch + exact hCont hBody hProject hMatch + · have hNoMapping : irContract.usesMapping = false := by + exact Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_noMapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots + inner fn err nativeYul htxNormalized hcalldataSizeFits hcompile + hNoMapping hLowerBlock hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + exact ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + +/-- Native-vs-IR selector-hit error theorem for a supported generated runtime. + +The emitted-runtime mapping split and concrete dispatcher lowering are hidden. +The remaining obligations are the selected lowered body error execution, +projection of that native error, and the resulting IR/native match. -/ +private theorem nativeGeneratedCallDispatcherResult_selector_hit_error_matchesIR_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) := by + have hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := + generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds_atFuel + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + state observableSlots inner nextSwitchId functions fn err nativeYul + (by simpa [reservedNames] using hLowerBlock) + hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping + (by simpa [reservedNames] using hLowerCases) + refine ⟨reservedNames, switchStart, cases', body', bodyStart, bodyEnd, + hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro hBody hProject hMatch + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcherWithMapping, functions] using + hNativeDispatcherExec hFuel + (by simpa [reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody) + (by simpa using hProject) + hMatch + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_atFuel + (nativeRuntimeDispatcherFuel irContract) irContract tx state + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn err nativeYul hLowerBlock hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hBody hProject hMatch + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcher [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcher] using + hNativeDispatcherExec hFuel + (by simpa [nativeContractOfDispatcher] using hBody) + (by simpa using hProject) + hMatch + +/-- Artifact-fixed native-vs-IR selector-hit error theorem for a supported +generated runtime. + +This is the halt-channel-friendly form of +`nativeGeneratedCallDispatcherResult_selector_hit_error_matchesIR_of_compile_ok_supported`: +the selected case artifacts are fixed before the concrete `err/nativeYul` pair +is chosen by executing the selected body. -/ +private theorem nativeGeneratedCallDispatcherResult_selector_hit_error_artifact_matchesIR_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + (∀ (err : EvmYul.Yul.Exception) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) := by + have hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := + generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds_atFuel_artifact + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + state observableSlots inner nextSwitchId functions fn + (by simpa [reservedNames] using hLowerBlock) + hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping + (by simpa [reservedNames] using hLowerCases) + refine ⟨reservedNames, switchStart, cases', midN, body', bodyStart, bodyEnd, + by simpa [reservedNames] using hLowerCases, hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro err nativeYul hBody hProject hMatch + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcherWithMapping, functions] using + hNativeDispatcherExec err nativeYul hFuel + (by simpa [reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody) + (by simpa using hProject) + hMatch + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_atFuel_artifact + (nativeRuntimeDispatcherFuel irContract) irContract tx state + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn hLowerBlock hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro err nativeYul hBody hProject hMatch + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcher [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcher] using + hNativeDispatcherExec err nativeYul hFuel + (by simpa [nativeContractOfDispatcher] using hBody) + (by simpa using hProject) + hMatch + +/-- Selector-hit error native-vs-IR theorem with native lowering produced from +`SupportedSpec + compile`. + +The selected-body error execution/projection/result-match obligations remain +inside the returned continuation. -/ +theorem nativeGeneratedCallDispatcherResult_selector_hit_error_matchesIR_exists_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (nativeContract : EvmYul.Yul.Ast.YulContract), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_exists + hcompile hSupported with + ⟨nativeContract, hLowerRuntime⟩ + rcases + nativeGeneratedCallDispatcherResult_selector_hit_error_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots nativeContract + fn err nativeYul hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap with + ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + exact ⟨nativeContract, hLowerRuntime, reservedNames, n0, cases', + body', bodyStart, bodyEnd, hCase, hBodyLower, hCont⟩ + +/-- Native-vs-IR selector-hit success theorem for a supported generated runtime. + +The emitted-runtime mapping split and concrete dispatcher lowering are hidden. +The remaining obligations are the selected lowered body normal execution, +matched-flag preservation, projection of the restored native state, and the +resulting IR/native match. -/ +private theorem nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) := by + have hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := + generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds_atFuel + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + state observableSlots inner nextSwitchId functions fn final nativeYul + (by simpa [reservedNames] using hLowerBlock) + hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping + (by simpa [reservedNames] using hLowerCases) + refine ⟨reservedNames, switchStart, cases', midN, body', bodyStart, bodyEnd, + by simpa [reservedNames] using hLowerCases, hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro hBody hPreservesMatched hProject hMatch + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcherWithMapping, functions] using + hNativeDispatcherExec hFuel + (by simpa [reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody) + (by simpa [reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hPreservesMatched) + (by simpa [nativeContractOfDispatcherWithMapping, functions] + using hProject) + hMatch + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_atFuel + (nativeRuntimeDispatcherFuel irContract) irContract tx state + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn final nativeYul hLowerBlock hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro hBody hPreservesMatched hProject hMatch + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcher [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcher] using + hNativeDispatcherExec hFuel + (by simpa [nativeContractOfDispatcher] using hBody) + (by simpa [nativeContractOfDispatcher] using hPreservesMatched) + (by simpa [nativeContractOfDispatcher] using hProject) + hMatch + +/-- Native-vs-IR selector-hit success theorem for a supported generated runtime +with the selected-body result quantified inside the continuation. + +This exposes deterministic lowered selector-hit artifacts before the body proof +chooses its normal `final/nativeYul` result. -/ +private theorem nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_forall_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + (∀ final nativeYul, + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) := by + have hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := + generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds_atFuel_forall + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + state observableSlots inner nextSwitchId functions fn + (by simpa [reservedNames] using hLowerBlock) + hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping + (by simpa [reservedNames] using hLowerCases) + refine ⟨reservedNames, switchStart, cases', midN, body', bodyStart, bodyEnd, + by simpa [reservedNames] using hLowerCases, hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro final nativeYul hBody hPreservesMatched hProject hMatch + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcherWithMapping [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcherWithMapping, functions] using + hNativeDispatcherExec final nativeYul hFuel + (by simpa [reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody) + (by simpa [reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hPreservesMatched) + (by simpa [nativeContractOfDispatcherWithMapping, functions] + using hProject) + hMatch + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_atFuel_forall + (nativeRuntimeDispatcherFuel irContract) irContract tx state + observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn hLowerBlock hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length + hcompile hSupported hNoMapping hLowerCases + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro final nativeYul hBody hPreservesMatched hProject hMatch + change nativeGeneratedCallDispatcherMatchesIROn irContract tx state + observableSlots (nativeContractOfDispatcher [.Block inner]) + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcher] using + hNativeDispatcherExec final nativeYul hFuel + (by simpa [nativeContractOfDispatcher] using hBody) + (by simpa [nativeContractOfDispatcher] using hPreservesMatched) + (by simpa [nativeContractOfDispatcher] using hProject) + hMatch + +/-- Selector-hit success native-vs-IR theorem with native lowering produced +from `SupportedSpec + compile`. + +The selected-body normal execution, matched-flag preservation, projection, and +result-match obligations remain inside the returned continuation. -/ +theorem nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_exists_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (nativeContract : EvmYul.Yul.Ast.YulContract), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_exists + hcompile hSupported with + ⟨nativeContract, hLowerRuntime⟩ + rcases + nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots nativeContract + fn final nativeYul hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap with + ⟨reservedNames, n0, cases', _midN, body', bodyStart, bodyEnd, + _hLowerCases, hCase, hBodyLower, hCont⟩ + exact ⟨nativeContract, hLowerRuntime, reservedNames, n0, cases', + body', bodyStart, bodyEnd, hCase, hBodyLower, hCont⟩ + +/-- Selector-hit lowered-artifact theorem for a supported generated runtime. + +Unlike the selector-hit success theorem, this exposes the selected native case +body without fixing a `final` native state or projected `YulResult`. This is the +artifact source needed by the future body-semantics bridge. -/ +private theorem nativeGeneratedSelectorHitLoweredArtifacts_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) : + ∃ (reservedNames : List String) (_n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) := by + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames 0 irContract.functions inner nextSwitchId + tx.functionSelector fn + (by simpa [reservedNames] using hLowerBlock) + hFind with + ⟨_body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + _hInner, hLowerCases, hCase, hBodyLower⟩ + exact ⟨reservedNames, switchStart, cases', body', bodyStart, bodyEnd, + hCase, by simpa [reservedNames] using hBodyLower⟩ + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + irContract.functions inner tx.functionSelector fn hLowerBlock hFind with + ⟨_body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + _hInner, hLowerCases, hCase, hBodyLower⟩ + exact ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower⟩ + +/-- Selector-hit success lowered artifacts for a supported generated runtime, +including the direct lowered user function body. + +The generic artifact theorem above exposes the selected generated +`switchCaseBody fn` wrapper. This success-branch variant also exposes the +lowered `fn.body` with the same final switch id, which is the exact native body +target needed by the remaining function-body semantics bridge. -/ +private theorem nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = .ok (bodyNative, bodyEnd) := by + have hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size := + generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange + let dummyNativeState : EvmYul.Yul.State := + (inferInstance : Inhabited EvmYul.Yul.State).default + let dummyYul : YulResult := + { success := false + returnValue := none + finalStorage := state.storage + finalMappings := Compiler.Proofs.storageAsMappings state.storage + events := state.events } + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + reservedNames 0 irContract.functions dispatcher nextSwitchId + hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + by_cases hPayable : fn.payable + · rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_withSwitchIds_generated_prefix + 0 reservedNames 0 irContract tx state observableSlots inner + nextSwitchId functions fn dummyNativeState dummyYul + (by simpa [reservedNames] using hLowerBlock) + hFind hSelectorRange hNoWrap hFunctionSelectorsRange + (by simpa using hPayable) hguards hArgs with + ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, _hCont⟩ + exact ⟨reservedNames, switchStart, cases', midN, body', bodyNative, + bodyStart, bodyEnd, userBodyStart, + by simpa [reservedNames] using hLowerCases, + hCase, + by simpa [reservedNames] using hBodyLower, + by simpa [reservedNames] using hUserBodyLower⟩ + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_withSwitchIds_generated_prefix + 0 reservedNames 0 irContract tx state observableSlots inner + nextSwitchId functions fn dummyNativeState dummyYul + (by simpa [reservedNames] using hLowerBlock) + hFind hSelectorRange hNoWrap hFunctionSelectorsRange hNonPayable + hguards hArgs with + ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, _hCont⟩ + exact ⟨reservedNames, switchStart, cases', midN, body', bodyNative, + bodyStart, bodyEnd, userBodyStart, + by simpa [reservedNames] using hLowerCases, + hCase, + by simpa [reservedNames] using hBodyLower, + by simpa [reservedNames] using hUserBodyLower⟩ + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + by_cases hPayable : fn.payable + · rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_generated_prefix + 0 irContract tx state observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn dummyNativeState dummyYul hLowerBlock hFind hSelectorRange + hNoWrap hFunctionSelectorsRange (by simpa using hPayable) + hguards hArgs with + ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, + hUserBodyLower, _hCont⟩ + exact ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, + hUserBodyLower⟩ + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_generated_prefix + 0 irContract tx state observableSlots inner + (∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) + fn dummyNativeState dummyYul hLowerBlock hFind hSelectorRange + hNoWrap hFunctionSelectorsRange hNonPayable hguards hArgs with + ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, + hUserBodyLower, _hCont⟩ + exact ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, + hUserBodyLower⟩ + +/-- Selector-hit success lowered artifacts for a supported generated runtime, +with native runtime lowering produced directly from `SupportedSpec + compile`. + +This packages the full lowering witness with the generated switch-case and +selected user-body lowering artifacts needed by the remaining native body +execution bridge. -/ +theorem nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_exists_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (nativeContract : EvmYul.Yul.Ast.YulContract), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_exists + hcompile hSupported with + ⟨nativeContract, hLowerRuntime⟩ + rcases + nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots + nativeContract fn hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap hguards hArgs with + ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower⟩ + exact ⟨nativeContract, hLowerRuntime, reservedNames, n0, cases', midN, + body', bodyNative, bodyStart, bodyEnd, userBodyStart, hLowerCases, hCase, + hBodyLower, hUserBodyLower⟩ + +/-- Selector-hit lowered artifacts plus compile-derived selected-body closure. + +This is the concrete artifact handoff for the remaining selected-body native +execution theorem: it exposes the actual lowered `fn.body` artifacts selected +by the dispatcher proof together with the compile-derived `BridgedStmts` and +calldata-threshold facts. It intentionally does not claim native execution or +projection semantics for the selected body. -/ +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_artifacts_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (fn : IRFunction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (nativeContract : EvmYul.Yul.Ast.YulContract), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body ∧ + 4 + fn.params.length * 32 < EvmYul.UInt256.size := by + rcases + nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_exists_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots fn hcompile + hFind hSelectorRange hSelectorsRange hNoWrap hguards hArgs with + ⟨nativeContract, hLowerRuntime, reservedNames, n0, cases', midN, body', + bodyNative, bodyStart, bodyEnd, userBodyStart, hLowerCases, hCase, + hBodyLower, hUserBodyLower⟩ + rcases + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_closure_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile fn reservedNames + userBodyStart hFind with + ⟨hBridged, _hLowered, hThreshold⟩ + exact ⟨nativeContract, hLowerRuntime, reservedNames, n0, cases', midN, + body', bodyNative, bodyStart, bodyEnd, userBodyStart, hLowerCases, hCase, + hBodyLower, hUserBodyLower, hBridged, hThreshold⟩ + +/-- Selector-hit bridge premise for the final generated-dispatcher composition. + +The selector miss case is closed generically by +`nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_of_compile_ok_supported`. +This predicate isolates the remaining selector-hit obligation: once the +generated runtime has lowered and `interpretIR` selected a function, the native +generated `callDispatcher` result must match the IR result. Proving this from +native execution of `lowerStmtsNativeWithSwitchIds ... fn.body` is the remaining +body-semantics bridge. -/ +private def NativeGeneratedSelectorHitBridge + (_spec : CompilationModel.CompilationModel) (_selectors : List Nat) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) + +/-- Success-only selector-hit bridge target. + +Generated selector-hit guard failures are discharged separately by +`NativeGeneratedSelectorHitBridge.of_success_bridge_and_generated_guard_reverts`. +This predicate names the remaining selected-function success case: the selected +function has passed generated value/calldata guards, so the native generated +`callDispatcher` result must match the IR result. -/ +def NativeGeneratedSelectorHitSuccessBridge + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + DispatchGuardsSafe fn tx → + fn.params.length ≤ tx.args.length → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) + +/-- Body-level selector-hit bridge target for generated native dispatchers. + +This is the precise remaining proof obligation exposed by +`nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_of_compile_ok_supported`: +for the selected lowered case body, prove native execution, preservation of the +matched flag, native result projection, and the final IR/native result match. +Once this is proved generically from `lowerStmtsNativeWithSwitchIds ... fn.body` +semantics, the remaining selector-hit work is reduced to threading these +obligations through the existing dispatcher continuation. -/ +private def NativeGeneratedSelectorHitBodyBridge + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + ∃ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) ∧ + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract)) ∧ + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) + +/-- User-body selector-hit bridge target for generated native dispatchers. + +This is the narrower form of `NativeGeneratedSelectorHitBodyBridge`: after the +generated calldata/value guards have been peeled, the remaining native semantic +obligation is over the direct lowering of `fn.body`. This is the theorem shape +the generic native function-body correctness proof should eventually supply. -/ +private def NativeGeneratedSelectorHitUserBodyBridge + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∃ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) ∧ + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) ∧ + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final, [])) = + nativeYul ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) + +/-- Native user-body fuel remaining after the generated selector-hit prefix. + +The payable path contributes one less generated guard than the non-payable +path, so the direct lowered `fn.body` proof must use the same split as the +generated-prefix dispatcher lemmas. -/ +noncomputable def nativeGeneratedSelectorHitUserBodyFuel + (irContract : IRContract) (fn : IRFunction) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) : Nat := + if fn.payable then + nativeRuntimeDispatcherFuel irContract - (cases'.length + 23) + else + nativeRuntimeDispatcherFuel irContract - (cases'.length + 24) + +/-- Exact-fuel user-body selector-hit bridge target. + +This is the fuel-aligned version of `NativeGeneratedSelectorHitUserBodyBridge`: +the body execution premise matches the payable/non-payable generated-prefix +lemmas directly. -/ +private def NativeGeneratedSelectorHitUserBodyBridgeAtFuel + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∃ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) ∧ + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) ∧ + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final, [])) = + nativeYul ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) + +/-- Exact-fuel user-body selector-hit bridge target at the dispatcher result +projection boundary. + +This is the form consumed by the generated-prefix dispatcher wrappers: the +lowered `fn.body` still executes at the exact remaining fuel, but the projected +result is the state restored by `callDispatcher` after the dispatcher body +returns normally. -/ +private def NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∃ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) ∧ + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) ∧ + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) + +/-- Exact-fuel user-body selector-hit bridge target at the revived native +function-body boundary. + +Native execution of a generated function body naturally returns a checkpoint +when the body exits via `leave`. This bridge lets the body-semantics proof +project the revived native state directly; the small restoration lemma +`NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_revived` below then +converts it to the dispatcher-restored projection consumed by the generated +`callDispatcher` stack. -/ +private def NativeGeneratedSelectorHitUserBodyBridgeAtFuelRevived + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∃ (final : EvmYul.Yul.State) (nativeYul : YulResult) + (shared : EvmYul.SharedState EvmYul.OperationType.Yul) + (store : EvmYul.Yul.VarStore), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) ∧ + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) ∧ + final.reviveJump = EvmYul.Yul.State.Ok shared store ∧ + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) = + nativeYul ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) + +/-- Revived native function-body bridge with the IR side stated directly as the +selected function-body semantics. + +This is the boundary expected from the future native body-correctness theorem: +after the generated dispatcher prefix has selected a function and its success +guards are known, prove the direct lowered `fn.body` native execution and match +it against `execIRFunction`. The theorem +`NativeGeneratedSelectorHitUserBodyBridgeAtFuelRevived.of_execIRFunction` +below retargets this to the top-level `interpretIR` bridge consumed by the +generated dispatcher stack. -/ +private def NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + DispatchGuardsSafe fn tx → + fn.params.length ≤ tx.args.length → + ∃ (final : EvmYul.Yul.State) (nativeYul : YulResult) + (shared : EvmYul.SharedState EvmYul.OperationType.Yul) + (store : EvmYul.Yul.VarStore), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) ∧ + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) ∧ + final.reviveJump = EvmYul.Yul.State.Ok shared store ∧ + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) = + nativeYul ∧ + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok nativeYul) + +/-- Revived native function-body execution bridge without matched-flag +preservation. + +This separates the semantic part of the future native body-correctness theorem +from the dispatcher-local matched-temp preservation proof. The preservation +side can be supplied independently from native switch freshness and +per-statement no-write facts, then recombined by +`NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_and_preserves`. +-/ +private def NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + DispatchGuardsSafe fn tx → + fn.params.length ≤ tx.args.length → + ∃ (final : EvmYul.Yul.State) (nativeYul : YulResult) + (shared : EvmYul.SharedState EvmYul.OperationType.Yul) + (store : EvmYul.Yul.VarStore), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) ∧ + final.reviveJump = EvmYul.Yul.State.Ok shared store ∧ + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) = + nativeYul ∧ + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok nativeYul) + +/-- Switch-case body bridge for selected functions that exit through +EVMYulLean's halt channel (`stop`/`return`). + +This keeps halt-style successful Solidity bodies out of the normal `.ok final` +bridge. The native dispatcher already treats `YulHalt` through the selector-hit +error theorem, while the IR side still compares against the selected +`execIRFunction` result under the generated success guards. -/ +private def NativeGeneratedSelectorHitBodyHaltExecBridgeAtFuel + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + DispatchGuardsSafe fn tx → + fn.params.length ≤ tx.args.length → + ∃ (haltState : EvmYul.Yul.State) (haltValue : EvmYul.Yul.Ast.Literal) + (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) ∧ + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = + nativeYul ∧ + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok nativeYul) + +/-- Direct selected-user-body halt bridge. + +This is the halt-channel companion to +`NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived`: it targets the +lowered `fn.body` directly when the generated user body exits through +`stop`/`return`, which EVMYulLean represents as `YulHalt`. -/ +def NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + DispatchGuardsSafe fn tx → + fn.params.length ≤ tx.args.length → + ∃ (haltState : EvmYul.Yul.State) (haltValue : EvmYul.Yul.Ast.Literal) + (nativeYul : YulResult), + (∀ (_pre : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)), + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) ∧ + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = + nativeYul ∧ + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok nativeYul) + +/-- Lift a direct selected-user-body halt proof through the generated +selector-hit success prefix. + +The direct body bridge executes `fn.body` after the dispatcher has installed +the selector-hit marker. This adapter discharges the generated comment no-op +and value/calldata guards, producing the whole selected `switchCaseBody fn` +halt bridge. -/ +private theorem NativeGeneratedSelectorHitBodyHaltExecBridgeAtFuel.of_selected_user_body_halt + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFuelPayable : + ∀ (fn : IRFunction) (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), + fn.payable = true → + cases'.length + 23 ≤ nativeRuntimeDispatcherFuel irContract) + (hFuelNonPayable : + ∀ (fn : IRFunction) (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), + fn.payable = false → + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract) + (hUserBodyHalt : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots) : + NativeGeneratedSelectorHitBodyHaltExecBridgeAtFuel irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' body' bodyStart bodyEnd + hLowerRuntime hFind hCase hBodyLower hguards hArgs + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd + (by simpa using hPayable) hBodyLower with + ⟨guardBody, bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + rcases hUserBodyHalt nativeContract fn reservedNames n0 cases' + bodyNative bodyEnd userBodyStart hLowerRuntime hFind hUserBodyLower + hguards hArgs with + ⟨haltState, haltValue, nativeYul, hBody, hProject, hMatch⟩ + refine ⟨haltState, haltValue, nativeYul, ?_, hProject, hMatch⟩ + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_payable_prefix_eq + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + guardBody bodyNative nativeContract (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt + fn tx hguards) + (by + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + exact Nat.add_le_add_left hMul 4) + have hFuelEq : + suffix.length + + (1 + (11 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 23)))) = + suffix.length + + (1 + (7 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)))) := by + have hBound := hFuelPayable fn cases' (by simpa using hPayable) + omega + simpa [nativeGeneratedSelectorHitUserBodyFuel, hPayable, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, hFuelEq] using + hPrefix.trans (hBody pre suffix) + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, userBodyStart, + hBodyShape, hUserBodyLower⟩ + rcases hUserBodyHalt nativeContract fn reservedNames n0 cases' + bodyNative bodyEnd userBodyStart hLowerRuntime hFind hUserBodyLower + hguards hArgs with + ⟨haltState, haltValue, nativeYul, hBody, hProject, hMatch⟩ + refine ⟨haltState, haltValue, nativeYul, ?_, hProject, hMatch⟩ + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_nonpayable_prefix_eq + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + callvalueGuardBody calldataGuardBody bodyNative nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + (4 + fn.params.length * 32) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable + fn tx hguards hNonPayable) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt + fn tx hguards) + (by + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + exact Nat.add_le_add_left hMul 4) + have hFuelEq : + suffix.length + + (1 + (12 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 24)))) = + suffix.length + + (1 + (7 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)))) := by + have hBound := hFuelNonPayable fn cases' (by simpa using hNonPayable) + omega + simpa [nativeGeneratedSelectorHitUserBodyFuel, hNonPayable, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, hFuelEq] using + hPrefix.trans (hBody pre suffix) + +/-- The whole selected-case halt bridge supplies the named selector-hit success +bridge by routing `YulHalt` through the dispatcher error channel. + +EVMYulLean represents `stop`/`return` as `YulHalt`, while the IR function +semantics records a successful `IRResult`. The artifact-fixed selector-hit +error continuation lets the selected body execute first, then feeds the +concrete halt state into the generated dispatcher proof. -/ +private theorem NativeGeneratedSelectorHitSuccessBridge.of_body_halt_exec_atFuel + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hHaltBridge : + NativeGeneratedSelectorHitBodyHaltExecBridgeAtFuel irContract tx state + observableSlots) : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots := by + intro nativeContract fn hLowerRuntime hFind hguards hArgs + rcases + nativeGeneratedCallDispatcherResult_selector_hit_error_artifact_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots + nativeContract fn hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap with + ⟨reservedNames, n0, cases', _midN, body', bodyStart, bodyEnd, + _hLowerCases, hCase, hBodyLower, hCont⟩ + rcases hHaltBridge nativeContract fn reservedNames n0 cases' body' + bodyStart bodyEnd hLowerRuntime hFind hCase hBodyLower hguards hArgs with + ⟨haltState, haltValue, nativeYul, hBody, hProject, hMatchExec⟩ + exact + hCont (EvmYul.Yul.Exception.YulHalt haltState haltValue) nativeYul + hBody hProject + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind hguards + hArgs hMatchExec) + +/-- A direct selected-user-body halt bridge supplies the public selector-hit +success bridge for supported generated runtimes. + +Unlike `NativeGeneratedSelectorHitBodyHaltExecBridgeAtFuel.of_selected_user_body_halt`, +this derives the generated prefix fuel bounds from the concrete lowered switch +cases exposed by the artifact-fixed dispatcher theorem, instead of requiring a +global bound for arbitrary case lists. -/ +private theorem NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_halt_exec_atFuel + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyHalt : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots) : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots := by + intro nativeContract fn hLowerRuntime hFind hguards hArgs + rcases + nativeGeneratedCallDispatcherResult_selector_hit_error_artifact_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots + nativeContract fn hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap with + ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCont⟩ + have hFuelBound24 : + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length_plus24 + hcompile hSupported hMapping hLowerCases + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length_plus24 + hcompile hSupported hNoMapping hLowerCases + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd + (by simpa using hPayable) hBodyLower with + ⟨guardBody, bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + rcases hUserBodyHalt nativeContract fn reservedNames n0 cases' + bodyNative bodyEnd userBodyStart hLowerRuntime hFind hUserBodyLower + hguards hArgs with + ⟨haltState, haltValue, nativeYul, hBody, hProject, hMatchExec⟩ + have hCaseBody : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) := by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_payable_prefix_eq + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + guardBody bodyNative nativeContract (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt + fn tx hguards) + (by + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + exact Nat.add_le_add_left hMul 4) + have hFuelEq : + suffix.length + + (1 + (11 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 23)))) = + suffix.length + + (1 + (7 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)))) := by + have hBound23 : cases'.length + 23 ≤ + nativeRuntimeDispatcherFuel irContract := by + omega + omega + simpa [nativeGeneratedSelectorHitUserBodyFuel, hPayable, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, hFuelEq] using + hPrefix.trans (hBody pre suffix) + exact + hCont (EvmYul.Yul.Exception.YulHalt haltState haltValue) nativeYul + hCaseBody hProject + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind hguards + hArgs hMatchExec) + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, userBodyStart, + hBodyShape, hUserBodyLower⟩ + rcases hUserBodyHalt nativeContract fn reservedNames n0 cases' + bodyNative bodyEnd userBodyStart hLowerRuntime hFind hUserBodyLower + hguards hArgs with + ⟨haltState, haltValue, nativeYul, hBody, hProject, hMatchExec⟩ + have hCaseBody : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) := by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_nonpayable_prefix_eq + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + callvalueGuardBody calldataGuardBody bodyNative nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + (4 + fn.params.length * 32) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable + fn tx hguards hNonPayable) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt + fn tx hguards) + (by + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + exact Nat.add_le_add_left hMul 4) + have hFuelEq : + suffix.length + + (1 + (12 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 24)))) = + suffix.length + + (1 + (7 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)))) := by + have hBound24 := hFuelBound24 + omega + simpa [nativeGeneratedSelectorHitUserBodyFuel, hNonPayable, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, hFuelEq] using + hPrefix.trans (hBody pre suffix) + exact + hCont (EvmYul.Yul.Exception.YulHalt haltState haltValue) nativeYul + hCaseBody hProject + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind hguards + hArgs hMatchExec) + +/-- Direct selected-user-body execution bridge without switch-case lowering +artifacts. + +This is the narrowest current success-case target for the future native +function-body theorem: the selected `fn.body` has lowered successfully, the +generated success guards are known, and executing the lowered body at the exact +dispatcher-provided fuel projects to the selected IR function semantics. The +small projection theorem below threads this cleaner body target into the +existing dispatcher bridge that still carries switch-case evidence. -/ +private def NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + DispatchGuardsSafe fn tx → + fn.params.length ≤ tx.args.length → + ∃ (final : EvmYul.Yul.State) (nativeYul : YulResult) + (shared : EvmYul.SharedState EvmYul.OperationType.Yul) + (store : EvmYul.Yul.VarStore), + (∀ (_pre : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)), + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) ∧ + final.reviveJump = EvmYul.Yul.State.Ok shared store ∧ + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) = + nativeYul ∧ + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok nativeYul) + +/-- Empty selected user bodies execute as a native no-op and project to the same +observable result as `execIRFunction`. + +This is the base case for the remaining selected-function-body theorem. It also +records the transaction-entry invariant that stale IR return values are cleared +before function execution, matching the native transaction entry state. -/ +private theorem nativeResultsMatchOn_execIRFunction_empty_body_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hBody : fn.body = []) : + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store).reviveJump, [])))) := by + simp only [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn] + simp [hBody, applyIRTransactionContext, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId_reviveJump_eq] + constructor + · intro slot hSlot + exact + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_observableStorageSlot + nativeContract (YulTransaction.ofIR tx) state.storage state.events + (Compiler.runtimeCode irContract) observableSlots switchId store slot + hSlot).symm + · simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState] + using + (Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState_nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store) + +/-- Build the direct selected-user-body execution bridge for contracts whose +selected generated function body is empty. -/ +private theorem NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_empty_body + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hEmpty : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = []) : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody : fn.body = [] := hEmpty fn hFind + simp [hBody] at hUserBodyLower + rcases hUserBodyLower with ⟨rfl, _rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let final := + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) + have hFinalOk : ∃ shared store, final = EvmYul.Yul.State.Ok shared store := by + simp [final, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert] + rcases hFinalOk with ⟨shared, store, hFinalOk⟩ + refine ⟨final, nativeYul, shared, store, ?_, ?_, rfl, ?_⟩ + · intro _pre suffix + simpa [final] using + (Compiler.Proofs.YulGeneration.Backends.Native.exec_block_nil_ok_add_ten + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases') + suffix.length (some nativeContract) final) + · rw [hFinalOk] + rfl + · exact + nativeResultsMatchOn_execIRFunction_empty_body_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + hBody + +/-- Selected user bodies containing only `leave` execute as a native checkpoint +and project to the same observable result as `execIRFunction`. + +The native interpreter records `leave` as a revivable checkpoint, while the +legacy IR function interpreter treats it as a normal fall-through. After +`reviveJump`, both paths have the same observable storage, return value, and +events at the transaction-entry state. -/ +private theorem nativeResultsMatchOn_execIRFunction_leave_body_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hBody : fn.body = [.leave]) : + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store).setLeave).reviveJump, [])))) := by + simp only [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn] + unfold execIRFunction + simp [hBody, applyIRTransactionContext, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert, EvmYul.Yul.State.setLeave, + EvmYul.Yul.State.reviveJump] + constructor + · intro slot hSlot + exact + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_observableStorageSlot + nativeContract (YulTransaction.ofIR tx) state.storage state.events + (Compiler.runtimeCode irContract) observableSlots switchId store slot + hSlot).symm + · simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState] + using + (Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState_nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store) + +/-- Build the direct selected-user-body execution bridge for contracts whose +selected generated function body is exactly `leave`. -/ +private theorem NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hLeave : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [.leave]) : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody : fn.body = [.leave] := hLeave fn hFind + rw [hBody] at hUserBodyLower + simp [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons] at hUserBodyLower + rcases hUserBodyLower with ⟨rfl, _rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let initial := + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + let final := initial.setLeave + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) + have hReviveOk : + ∃ shared store, final.reviveJump = EvmYul.Yul.State.Ok shared store := by + simp [final, initial, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert, EvmYul.Yul.State.setLeave, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive] + rcases hReviveOk with ⟨shared, store, hRevive⟩ + refine ⟨final, nativeYul, shared, store, ?_, hRevive, rfl, ?_⟩ + · intro _pre suffix + simpa [final, initial] using + (Compiler.Proofs.YulGeneration.Backends.Native.exec_block_leave_ok_add_ten + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases') + suffix.length (some nativeContract) initial) + · exact + nativeResultsMatchOn_execIRFunction_leave_body_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + hBody + +/-- Selected user bodies consisting of a single `.block [.leave]` produce the +same observable result as the bare `.leave` body. + +The source `execIRFunction` enters the inner block (`execIRStmt` on `.block` +reduces to `execIRStmts` on the inner list) which itself reduces a single +`.leave` to `.continue`, and then falls through the (empty) outer tail. The +native lowering produces `[.Block [.Leave]]` whose execution sets the leave +flag on the outer state and then reviveJump strips it, so the observable +projection coincides with the bare `.leave` case. -/ +private theorem nativeResultsMatchOn_execIRFunction_block_leave_body_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hBody : fn.body = [.block [.leave]]) : + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store).setLeave).reviveJump, [])))) := by + simp only [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn] + unfold execIRFunction + simp [hBody, applyIRTransactionContext, execIRStmts, execIRStmt, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert, EvmYul.Yul.State.setLeave, + EvmYul.Yul.State.reviveJump] + constructor + · intro slot hSlot + exact + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_observableStorageSlot + nativeContract (YulTransaction.ofIR tx) state.storage state.events + (Compiler.runtimeCode irContract) observableSlots switchId store slot + hSlot).symm + · simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState] + using + (Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState_nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store) + +/-- Build the direct selected-user-body execution bridge for contracts whose +selected generated function body is exactly `[.block [.leave]]`. + +Lowering wraps the `.leave` in a `[.Block ...]` native statement, but the +outer dispatcher block also wraps the user body so we run a `.Block` of a +single inner `.Block [.Leave]`. This nests one extra level beyond +`.of_leave_body` and is closed by `exec_block_block_leave_ok_add_ten`. -/ +private theorem NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_block_leave + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hBlockLeave : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [.block [.leave]]) : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody : fn.body = [.block [.leave]] := hBlockLeave fn hFind + rw [hBody] at hUserBodyLower + simp [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_block, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + at hUserBodyLower + rcases hUserBodyLower with ⟨rfl, _rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let initial := + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + let final := initial.setLeave + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) + have hReviveOk : + ∃ shared store, final.reviveJump = EvmYul.Yul.State.Ok shared store := by + simp [final, initial, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert, EvmYul.Yul.State.setLeave, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive] + rcases hReviveOk with ⟨shared, store, hRevive⟩ + refine ⟨final, nativeYul, shared, store, ?_, hRevive, rfl, ?_⟩ + · intro _pre suffix + simpa [final, initial] using + (Compiler.Proofs.YulGeneration.Backends.Native.exec_block_block_leave_ok_add_ten + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases') + suffix.length (some nativeContract) initial) + · exact + nativeResultsMatchOn_execIRFunction_block_leave_body_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + hBody + +/-- Selected user bodies consisting of a single `.block []` produce the same +observable result as an empty body. + +The source `execIRFunction` enters the inner block (`execIRStmt` on `.block` +reduces to `execIRStmts` on the inner list) which returns `.continue` on the +empty list, and the outer `execIRStmts` falls through similarly. The native +lowering produces `[.Block []]` whose execution yields the entry state +unchanged (no `setLeave`), so `reviveJump` is the identity on it. -/ +private theorem nativeResultsMatchOn_execIRFunction_block_empty_body_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hBody : fn.body = [.block []]) : + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store).reviveJump, [])))) := by + simp only [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn] + unfold execIRFunction + simp [hBody, applyIRTransactionContext, execIRStmts, execIRStmt, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId_reviveJump_eq] + constructor + · intro slot hSlot + exact + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_observableStorageSlot + nativeContract (YulTransaction.ofIR tx) state.storage state.events + (Compiler.runtimeCode irContract) observableSlots switchId store slot + hSlot).symm + · simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState] + using + (Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState_nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store) + +/-- Build the direct selected-user-body execution bridge for contracts whose +selected generated function body is exactly `[.block []]`. + +Mirrors `.of_empty_body` (no leave flag set) but accounts for the additional +nested `.Block []` layer in the lowered native body. The native side +executes via `exec_block_block_nil_ok_add_ten` returning `.ok state`. -/ +private theorem NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_block_empty + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hBlockEmpty : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [.block []]) : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody : fn.body = [.block []] := hBlockEmpty fn hFind + rw [hBody] at hUserBodyLower + simp [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_block, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + at hUserBodyLower + rcases hUserBodyLower with ⟨rfl, _rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let final := + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) + have hFinalOk : ∃ shared store, final = EvmYul.Yul.State.Ok shared store := by + simp [final, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert] + rcases hFinalOk with ⟨shared, store, hFinalOk⟩ + refine ⟨final, nativeYul, shared, store, ?_, ?_, rfl, ?_⟩ + · intro _pre suffix + simpa [final] using + (Compiler.Proofs.YulGeneration.Backends.Native.exec_block_block_nil_ok_add_ten + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases') + suffix.length (some nativeContract) final) + · rw [hFinalOk] + rfl + · exact + nativeResultsMatchOn_execIRFunction_block_empty_body_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + hBody + +/-- Selected user bodies consisting of a single `.comment text` produce the +same observable result as an empty body. + +`.comment` is a source-level no-op (`execIRStmt (.comment _) state = .continue +state`), and its native lowering is `.Block []` per +`lowerStmtGroupNativeWithSwitchIds_comment`. So the dispatcher-wrapped body +becomes `.Block [.Block []]`, identical to the `.of_block_empty` native shape; +the source side likewise falls through to `.continue stateWithParams`. The +proof reuses the same `nativeSwitchStoreMarkedPrefixStateForId_reviveJump_eq` +identity. -/ +private theorem nativeResultsMatchOn_execIRFunction_singleton_comment_body_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (text : String) + (hBody : fn.body = [.comment text]) : + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store).reviveJump, [])))) := by + simp only [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn] + unfold execIRFunction + simp [hBody, applyIRTransactionContext, execIRStmts, execIRStmt, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId_reviveJump_eq] + constructor + · intro slot hSlot + exact + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_observableStorageSlot + nativeContract (YulTransaction.ofIR tx) state.storage state.events + (Compiler.runtimeCode irContract) observableSlots switchId store slot + hSlot).symm + · simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState] + using + (Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState_nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store) + +/-- Build the direct selected-user-body execution bridge for contracts whose +selected generated function body is exactly `[.comment text]` for some +text. + +`.comment` lowers to `.Block []`, so the dispatcher-wrapped native body is +`.Block [.Block []]` — identical to the `.of_block_empty` shape; this +constructor consequently reuses `exec_block_block_nil_ok_add_ten`. -/ +private theorem NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_singleton_comment + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hComment : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∃ text, fn.body = [.comment text]) : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + obtain ⟨text, hBody⟩ := hComment fn hFind + rw [hBody] at hUserBodyLower + rcases Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_comment_head_eq + reservedNames userBodyStart text [] bodyNative bodyEnd hUserBodyLower + with ⟨rest', hShape, hRest⟩ + -- rest is empty so its lowering is empty + simp [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil] + at hRest + rcases hRest with ⟨hRest', _⟩ + subst hRest' + subst hShape + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let final := + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) + have hFinalOk : ∃ shared store, final = EvmYul.Yul.State.Ok shared store := by + simp [final, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert] + rcases hFinalOk with ⟨shared, store, hFinalOk⟩ + refine ⟨final, nativeYul, shared, store, ?_, ?_, rfl, ?_⟩ + · intro _pre suffix + simpa [final] using + (Compiler.Proofs.YulGeneration.Backends.Native.exec_block_block_nil_ok_add_ten + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases') + suffix.length (some nativeContract) final) + · rw [hFinalOk] + rfl + · exact + nativeResultsMatchOn_execIRFunction_singleton_comment_body_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + text hBody + +/-- Selected user bodies containing only `stop` execute as a native halt and +project to the same observable result as `execIRFunction`. -/ +private theorem nativeResultsMatchOn_execIRFunction_stop_body_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hBody : fn.body = [Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) : + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store) + ⟨0⟩)))) := by + simp only [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn] + rw [Compiler.Proofs.IRGeneration.execIRFunction_single_stop fn tx.args + (applyIRTransactionContext tx state) hBody] + simp [applyIRTransactionContext] + constructor + · intro slot hSlot + exact + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId_materializedStorageSlot + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store slot + (Compiler.Proofs.YulGeneration.Backends.Native.observableSlot_mem_materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots slot hSlot)).symm + · simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState] + using + (Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState_nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId store) + +/-- Build the direct selected-user-body halt bridge for contracts whose +selected generated function body is exactly `stop`. -/ +private theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_stop_body + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hStop : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody : fn.body = [Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])] := + hStop fn hFind + rw [hBody] at hUserBodyLower + simp [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_expr, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] at hUserBodyLower + rcases hUserBodyLower with ⟨rfl, _rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let haltState := + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState ⟨0⟩)) + refine ⟨haltState, ⟨0⟩, nativeYul, ?_, rfl, ?_⟩ + · intro _pre suffix + simpa [switchId, haltState] using + (Compiler.Proofs.YulGeneration.Backends.Native.exec_block_stop_halt_add_ten + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases') + suffix.length (some nativeContract) haltState) + · simpa [switchId, haltState, nativeYul] using + (nativeResultsMatchOn_execIRFunction_stop_body_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + hBody) + +/-- Matched-flag preservation bridge for direct lowered selected user bodies. + +This is the dispatcher-local half factored out of +`NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived`; it contains no IR +semantics and can be proved from freshness/no-write facts independently of the +future native body execution theorem. -/ +private def NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel + (irContract : IRContract) + (tx : IRTransaction) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some nativeContract) + +/-- Unified selected-user-body result boundary. + +Native lowered function bodies can finish either by returning normally to the +Yul function frame (`leave`, represented by `.ok final` with a revivable +checkpoint) or by a generated EVM halt such as `stop`/`return` (represented by +`YulHalt`). This predicate keeps the remaining native function-body theorem +from having to pick one dispatcher adapter prematurely. The normal path also +carries the dispatcher-local matched-flag preservation fact needed by the +generated switch-case continuation. -/ +private def NativeGeneratedSelectedUserBodyResultBridgeAtFuel + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots ∨ + (NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots ∧ + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx) + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hHalt : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + Or.inl hHalt + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_stop_body + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hStop : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt irContract tx state + observableSlots + (NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_stop_body + irContract tx state observableSlots hStop) + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_preserves + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hPreserves : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + Or.inr ⟨hExec, hPreserves⟩ + +/-- Project the semantic execution half out of the existing all-in-one selected +user-body execution bridge. -/ +private theorem NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_exec_bridge + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) : + NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower hUserBodyLower + hguards hArgs + rcases hBridge nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, _hPreserves, hRevive, hProject, + hMatch⟩ + exact ⟨final, nativeYul, shared, store, hBody, hRevive, hProject, hMatch⟩ + +/-- Project the direct selected-user-body execution target into the existing +dispatcher-shaped exec-only bridge. -/ +private theorem NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_selected_user_body_exec_only + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hBridge : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) : + NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart hLowerRuntime hFind _hCase _hBodyLower hUserBodyLower + hguards hArgs + unfold NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived at hBridge + rcases hBridge nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart hLowerRuntime hFind hUserBodyLower hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, hRevive, hProject, hMatch⟩ + refine ⟨final, nativeYul, shared, store, ?_, hRevive, hProject, hMatch⟩ + intro pre suffix _hCases + exact hBody pre suffix + +/-- Project the dispatcher-local preservation half out of the existing +all-in-one selected user-body execution bridge. -/ +private theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_exec_bridge + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) + (hguards : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + DispatchGuardsSafe fn tx) + (hArgs : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params.length ≤ tx.args.length) : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower hUserBodyLower + pre suffix hCases + rcases hBridge nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower (hguards fn hFind) (hArgs fn hFind) with + ⟨_final, _nativeYul, _shared, _store, _hBody, hPreserves, _hRevive, + _hProject, _hMatch⟩ + exact hPreserves pre suffix hCases + +/-- Build the selected user-body preservation bridge from local no-write and +per-statement preservation facts for the lowered native body. -/ +private theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_forall_stmt_write_not_mem + (irContract : IRContract) + (tx : IRTransaction) + (hFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ stmt, stmt ∈ bodyNative → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt) + (hStmtPreserves : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ stmt, stmt ∈ bodyNative → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt (some nativeContract)) : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower hUserBodyLower + _pre _suffix _hCases + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_forall_stmt_write_not_mem + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some nativeContract) + (hFresh nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower) + (hStmtPreserves nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower) + +/-- Build the selected user-body preservation bridge from block-level native +write-name freshness and per-statement preservation. + +This is the no-mapping-friendly preservation adapter: callers can discharge +freshness once for the whole lowered body and provide preservation facts for +the actual lowered runtime contract, without requiring the mapping-helper +contract shape. -/ +private theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_nativeStmtsWriteNames_not_mem + (irContract : IRContract) + (tx : IRTransaction) + (hFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames + bodyNative) + (hStmtPreserves : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ stmt, stmt ∈ bodyNative → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt (some nativeContract)) : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower hUserBodyLower + _pre _suffix _hCases + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some nativeContract) + (hFresh nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower) + (hStmtPreserves nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower) + +/-- Package direct selected-body execution with block-fresh preservation into +the unified selected-body result boundary. + +This is the narrow normal-return target for the remaining generic native +function-body theorem: prove selected-body execution against `execIRFunction`, +prove the lowered body cannot disturb the matched flag, and the dispatcher +success bridge can consume the result without exposing either internal premise +separately. -/ +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_nativeStmtsWriteNames_not_mem + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames + bodyNative) + (hStmtPreserves : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ stmt, stmt ∈ bodyNative → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt (some nativeContract)) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_preserves + irContract tx state observableSlots hExec + (NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_nativeStmtsWriteNames_not_mem + irContract tx hFresh hStmtPreserves) + +private theorem nativeStmtsWriteNames_not_mem_of_two_prefix + (name : String) (a b : EvmYul.Yul.Ast.Stmt) + (rest : List EvmYul.Yul.Ast.Stmt) : + name ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames + (a :: b :: rest) → + name ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames rest := by + intro hFresh + exact + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtsWriteNames_tail_not_mem_of_cons_not_mem + name b rest + (Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtsWriteNames_tail_not_mem_of_cons_not_mem + name a (b :: rest) hFresh) + +private theorem nativeStmtsWriteNames_not_mem_of_three_prefix + (name : String) (a b c : EvmYul.Yul.Ast.Stmt) + (rest : List EvmYul.Yul.Ast.Stmt) : + name ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames + (a :: b :: c :: rest) → + name ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames rest := by + intro hFresh + exact + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtsWriteNames_tail_not_mem_of_cons_not_mem + name c rest + (nativeStmtsWriteNames_not_mem_of_two_prefix name a b (c :: rest) + hFresh) + +private theorem lowerStmtsNativeWithSwitchIds_ok_body_eq_of_same_input + (reservedNames : List String) (start : Nat) + (body : List Yul.YulStmt) + (bodyNative₁ bodyNative₂ : List EvmYul.Yul.Ast.Stmt) + (end₁ end₂ : Nat) + (h₁ : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames start body = .ok (bodyNative₁, end₁)) + (h₂ : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames start body = .ok (bodyNative₂, end₂)) : + bodyNative₁ = bodyNative₂ ∧ end₁ = end₂ := by + rw [h₁] at h₂ + simp only [Except.ok.injEq, Prod.mk.injEq] at h₂ + exact h₂ + +private theorem nativeGeneratedSelectedUserBodyMatchedFresh_payable_of_caseFresh + (fn : IRFunction) (reservedNames : List String) + (matchedName : String) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat) + (hPayable : fn.payable = true) + (hBodyLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd)) + (hCaseFresh : + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames body') : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) ∧ + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative := by + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd hPayable hBodyLower with + ⟨guardBody, bodyNative, userBodyStart, hBodyShape, hBodyLower'⟩ + rw [hBodyShape] at hCaseFresh + refine ⟨bodyNative, userBodyStart, hBodyLower', ?_⟩ + exact nativeStmtsWriteNames_not_mem_of_two_prefix matchedName + (EvmYul.Yul.Ast.Stmt.Block []) + (EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + guardBody) + bodyNative hCaseFresh + +private theorem nativeGeneratedSelectedUserBodyMatchedFresh_nonpayable_of_caseFresh + (fn : IRFunction) (reservedNames : List String) + (matchedName : String) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat) + (hNonPayable : fn.payable = false) + (hBodyLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd)) + (hCaseFresh : + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames body') : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) ∧ + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative := by + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, userBodyStart, + hBodyShape, hBodyLower'⟩ + rw [hBodyShape] at hCaseFresh + refine ⟨bodyNative, userBodyStart, hBodyLower', ?_⟩ + exact nativeStmtsWriteNames_not_mem_of_three_prefix matchedName + (EvmYul.Yul.Ast.Stmt.Block []) + (EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "callvalue" [])) + callvalueGuardBody) + (EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + calldataGuardBody) + bodyNative hCaseFresh + +private theorem nativeGeneratedSelectedUserBodyMatchedFresh_of_switchFresh + (tx : IRTransaction) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat) + (hCase : + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body')) + (hBodyLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd)) + (hFresh : + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative := by + let switchId := Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let matchedName := Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName switchId + have hCaseFresh : + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames body' := by + simpa [matchedName] using + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_find_hit_matched_not_mem + switchId + tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' hFresh hCase + by_cases hPayable : fn.payable + · simpa [matchedName] using + nativeGeneratedSelectedUserBodyMatchedFresh_payable_of_caseFresh + fn reservedNames matchedName body' bodyStart bodyEnd + (by simpa using hPayable) hBodyLower hCaseFresh + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + simpa [matchedName] using + nativeGeneratedSelectedUserBodyMatchedFresh_nonpayable_of_caseFresh + fn reservedNames matchedName body' bodyStart bodyEnd hNonPayable + hBodyLower hCaseFresh + +/-- Compile-derived selected-body closure plus the dispatcher-marker freshness +fact obtained from generated switch-case freshness. + +This is the Track 1/5/6 handoff fact for the selected-body bridge: supported +compiler output supplies the bridged source body and calldata threshold, while +`nativeSwitchTempsFreshForNativeBodies` on the generated cases is enough to +strip the generated guard prefix and recover freshness for the actual lowered +user body. -/ +private theorem selectedUserBodyClosureAndMatchedFresh_of_compile_ok_supported_switchFresh + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hCase : + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body')) + (hBodyLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd)) + (hFresh : + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body ∧ + (∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) ∧ + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames + bodyNative) ∧ + 4 + fn.params.length * 32 < EvmYul.UInt256.size := by + have hBridged : + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body := + generatedRuntimeSelectedFunctionBodyBridged_of_compile_ok_supported + hcompile hSupported hFind + have hMatchedFresh := + nativeGeneratedSelectedUserBodyMatchedFresh_of_switchFresh + tx fn reservedNames n0 cases' body' bodyStart bodyEnd + hCase hBodyLower hFresh + exact ⟨hBridged, hMatchedFresh, + generatedFunctionCalldataThreshold_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile fn hFind⟩ + +private theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_mappingFreePreservableStraightStmts + (irContract : IRContract) + (tx : IRTransaction) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreePreservableStraightStmts + fn.body) + (hFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative) : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower hUserBodyLower + _pre _suffix _hCases + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) + reservedNames userBodyStart fn.body bodyNative bodyEnd + (some nativeContract) + (hBodyStraight fn hFind) + hUserBodyLower + (hFresh nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower) + +/-- Package direct selected-body execution with the mapping-free straight-body +preservation closure into the unified selected-body result bridge. -/ +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_mappingFreePreservableStraightStmts + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreePreservableStraightStmts + fn.body) + (hFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_preserves + irContract tx state observableSlots hExec + (NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_mappingFreePreservableStraightStmts + irContract tx hBodyStraight hFresh) + +/-- Package direct selected-body execution with historical straight-body +closure after excluding the mapping helper recursively. + +This adapter keeps no-mapping generated bodies on the existing +`BridgedStraightStmts` closure surface while routing preservation through the +actual-runtime `NativeMappingFreePreservableStraightStmts` harness path. -/ +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mappingFree + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts fn.body) + (hMappingFreeSide : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∀ stmt, stmt ∈ fn.body → + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreeSideConditionForBridgedStraightStmt + stmt) + (hFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_mappingFreePreservableStraightStmts + irContract tx state observableSlots hExec + (fun fn hFind => + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreePreservableStraightStmts.of_bridgedStraightStmts + (hBodyStraight fn hFind) (hMappingFreeSide fn hFind)) + hFresh + +/-- Build the direct selected user-body preservation bridge for mapping-helper +generated runtimes whose selected source body is in the straight bridged +fragment. + +This is the preservation-side counterpart of the remaining function-body +execution theorem: once the selected lowered body is known fresh for the +dispatcher matched flag, the native harness can discharge matched-flag +preservation from the straight-body closure facts without exposing the +mapping-helper contract shape to public callers. -/ +private theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_bridgedStraightStmts_mapping + (spec : CompilationModel.CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts fn.body) + (hSide : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∀ stmt, stmt ∈ fn.body → + Compiler.Proofs.YulGeneration.Backends.Native.NativePreservableSideConditionForBridgedStraightStmt + stmt) + (hFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative) : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower hUserBodyLower + _pre _suffix _hCases + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, _nextSwitchId, _hLowerDispatcher, hNativeContract⟩ + subst nativeContract + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_bridgedStraightStmts + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) + reservedNames userBodyStart fn.body bodyNative bodyEnd + (.Block dispatcher) + (hBodyStraight fn hFind) + (hSide fn hFind) + hUserBodyLower + (by + simpa using + hFresh (nativeContractOfDispatcherWithMapping dispatcher) fn + reservedNames n0 cases' body' bodyNative bodyStart bodyEnd + userBodyStart (by simpa [nativeContractOfDispatcherWithMapping] using + hLowerRuntime) hFind hCase hBodyLower hUserBodyLower) + +/-- Package direct selected-body execution with the mapping-helper straight-body +preservation closure into the unified selected-body result bridge. + +This keeps the mapping-specific native contract shape and straight-body +side-condition details behind the result boundary, leaving the remaining +generic function-body theorem to supply only direct native execution. -/ +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mapping + (spec : CompilationModel.CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hMapping : irContract.usesMapping = true) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts fn.body) + (hSide : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∀ stmt, stmt ∈ fn.body → + Compiler.Proofs.YulGeneration.Backends.Native.NativePreservableSideConditionForBridgedStraightStmt + stmt) + (hFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_preserves + irContract tx state observableSlots hExec + (NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_bridgedStraightStmts_mapping + spec selectors hSupported irContract tx hcompile hMapping hBodyStraight + hSide hFresh) + +/-- The generated `revert(0,0)` guard body cannot produce a normal `.ok` +state, so it vacuously preserves any dispatcher marker on successful +execution. -/ +private theorem NativeBlockPreservesWord_nativeRevertZeroZero + (name : EvmYul.Identifier) + (value : EvmYul.Literal) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + name value + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + codeOverride := by + refine + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_singleton + name value + Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt + codeOverride ?_ + simp only [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name value EvmYul.Operation.REVERT + [EvmYul.Yul.Ast.Expr.Lit (EvmYul.UInt256.ofNat 0), + EvmYul.Yul.Ast.Expr.Lit (EvmYul.UInt256.ofNat 0)] + codeOverride + (Compiler.Proofs.YulGeneration.Backends.Native.NativeEvalArgsPreservesWord_cons + name value (EvmYul.Yul.Ast.Expr.Lit (EvmYul.UInt256.ofNat 0)) + [EvmYul.Yul.Ast.Expr.Lit (EvmYul.UInt256.ofNat 0)] codeOverride + (Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lit + name value (EvmYul.UInt256.ofNat 0) codeOverride) + (Compiler.Proofs.YulGeneration.Backends.Native.NativeEvalArgsPreservesWord_cons + name value (EvmYul.Yul.Ast.Expr.Lit (EvmYul.UInt256.ofNat 0)) + [] codeOverride + (Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lit + name value (EvmYul.UInt256.ofNat 0) codeOverride) + (Compiler.Proofs.YulGeneration.Backends.Native.NativeEvalArgsPreservesWord_nil + name value codeOverride))) + (by + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_revert_values + name value) + +private theorem NativeExprPreservesWord_lowerExprNative_callvalue_any + (name : EvmYul.Identifier) + (value : EvmYul.Literal) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) : + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord + name value + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Compiler.Yul.YulExpr.call "callvalue" [])) + codeOverride := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name "callvalue" value [] EvmYul.Operation.CALLVALUE codeOverride + (by simp [Compiler.Proofs.YulGeneration.Backends.lookupRuntimePrimOp]) + (Compiler.Proofs.YulGeneration.Backends.Native.NativeEvalArgsPreservesWord_nil + name value codeOverride) + (Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_callvalue_values + name value) + +private theorem NativeExprPreservesWord_lowerExprNative_lt_calldatasize_lit_any + (name : EvmYul.Identifier) + (value : EvmYul.Literal) + (k : Nat) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) : + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord + name value + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Compiler.Yul.YulExpr.call "lt" + [Compiler.Yul.YulExpr.call "calldatasize" [], + Compiler.Yul.YulExpr.lit k])) + codeOverride := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name "lt" value + [Compiler.Yul.YulExpr.call "calldatasize" [], Compiler.Yul.YulExpr.lit k] + EvmYul.Operation.LT codeOverride + (by simp [Compiler.Proofs.YulGeneration.Backends.lookupRuntimePrimOp]) + (Compiler.Proofs.YulGeneration.Backends.Native.NativeEvalArgsPreservesWord_map_lowerExprNative_reverse + name value + [Compiler.Yul.YulExpr.call "calldatasize" [], Compiler.Yul.YulExpr.lit k] + codeOverride + (by + intro arg hArg + simp at hArg + rcases hArg with hArg | hArg + · subst arg + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name "calldatasize" value [] EvmYul.Operation.CALLDATASIZE + codeOverride + (by simp [Compiler.Proofs.YulGeneration.Backends.lookupRuntimePrimOp]) + (Compiler.Proofs.YulGeneration.Backends.Native.NativeEvalArgsPreservesWord_nil + name value codeOverride) + (Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_calldatasize_values + name value) + · subst arg + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_lit + name value k codeOverride)) + (Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_lt_values + name value) + +/-- Lift matched-flag preservation from a direct lowered selected user body to +the whole generated payable `switchCaseBody` wrapper. -/ +private theorem NativeBlockPreservesWord_switchCaseBody_payable_of_user_body + (fn : IRFunction) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) + (switchStart : Nat) + (body' guardBody bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat) + (hPayable : fn.payable = true) + (hBodyLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd)) + (hBodyShape : + body' = + EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Compiler.Yul.YulExpr.call "lt" + [Compiler.Yul.YulExpr.call "calldatasize" [], + Compiler.Yul.YulExpr.lit (4 + fn.params.length * 32)])) + guardBody :: + bodyNative) + (hUserPreserves : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative (some nativeContract)) : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) body' (some nativeContract) := by + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_revert_eq + reservedNames bodyStart fn body' bodyEnd hPayable hBodyLower with + ⟨bodyNative', userBodyStart', hShape, hUserBodyLower'⟩ + have hShapeEq : guardBody = [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] ∧ + bodyNative = bodyNative' := by + rw [hShape] at hBodyShape + simp at hBodyShape + exact ⟨hBodyShape.1.symm, hBodyShape.2.symm⟩ + rcases hShapeEq with ⟨hGuardBody, hBodyNativeEq⟩ + subst guardBody + subst bodyNative' + rw [hShape] + refine + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_cons_stmt + _ _ (.Block []) _ _ ?_ ?_ + · exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_block + _ _ [] _ (Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_nil _ _ _) + · refine + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_cons_stmt + _ _ _ _ _ ?_ ?_ + · exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_if_of_cond_preserves + _ _ _ _ _ + (NativeExprPreservesWord_lowerExprNative_lt_calldatasize_lit_any + _ _ (4 + fn.params.length * 32) _) + (NativeBlockPreservesWord_nativeRevertZeroZero _ _ _) + · exact hUserPreserves + +/-- Lift matched-flag preservation from a direct lowered selected user body to +the whole generated non-payable `switchCaseBody` wrapper. -/ +private theorem NativeBlockPreservesWord_switchCaseBody_nonpayable_of_user_body + (fn : IRFunction) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) + (switchStart : Nat) + (body' callvalueGuardBody calldataGuardBody bodyNative : + List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat) + (hNonPayable : fn.payable = false) + (hBodyLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd)) + (hBodyShape : + body' = + EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Compiler.Yul.YulExpr.call "callvalue" [])) + callvalueGuardBody :: + EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Compiler.Yul.YulExpr.call "lt" + [Compiler.Yul.YulExpr.call "calldatasize" [], + Compiler.Yul.YulExpr.lit (4 + fn.params.length * 32)])) + calldataGuardBody :: + bodyNative) + (hUserPreserves : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative (some nativeContract)) : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) body' (some nativeContract) := by + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨bodyNative', _userBodyStart', hShape, _hUserBodyLower'⟩ + have hShapeEq : + callvalueGuardBody = + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] ∧ + calldataGuardBody = + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] ∧ + bodyNative = bodyNative' := by + rw [hShape] at hBodyShape + simp at hBodyShape + exact ⟨hBodyShape.1.symm, hBodyShape.2.1.symm, hBodyShape.2.2.symm⟩ + rcases hShapeEq with ⟨hCallvalueGuardBody, hCalldataGuardBody, + hBodyNativeEq⟩ + subst callvalueGuardBody + subst calldataGuardBody + subst bodyNative' + rw [hShape] + refine + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_cons_stmt + _ _ (.Block []) _ _ ?_ ?_ + · exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_block + _ _ [] _ (Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_nil _ _ _) + · refine + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_cons_stmt + _ _ _ _ _ ?_ ?_ + · exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_if_of_cond_preserves + _ _ _ _ _ + (NativeExprPreservesWord_lowerExprNative_callvalue_any _ _ _) + (NativeBlockPreservesWord_nativeRevertZeroZero _ _ _) + · refine + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_cons_stmt + _ _ _ _ _ ?_ ?_ + · exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_if_of_cond_preserves + _ _ _ _ _ + (NativeExprPreservesWord_lowerExprNative_lt_calldatasize_lit_any + _ _ (4 + fn.params.length * 32) _) + (NativeBlockPreservesWord_nativeRevertZeroZero _ _ _) + · exact hUserPreserves + +/-- User-body matched-flag preservation implies preservation for the whole +generated selected case body. -/ +private theorem nativeGeneratedSelectorHitBodyPreservesMatched_of_user_body_preserves + (irContract : IRContract) + (tx : IRTransaction) + (hPreserves : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx) : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract) := by + intro nativeContract fn reservedNames n0 cases' body' bodyStart bodyEnd + hLowerRuntime hFind hCase hBodyLower pre suffix hCases + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd + (by simpa using hPayable) hBodyLower with + ⟨guardBody, bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + have hUserPreserves : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some nativeContract) := + hPreserves nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower pre suffix hCases + exact + NativeBlockPreservesWord_switchCaseBody_payable_of_user_body + fn nativeContract reservedNames n0 body' guardBody bodyNative bodyStart + bodyEnd (by simpa using hPayable) hBodyLower hBodyShape hUserPreserves + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, userBodyStart, + hBodyShape, hUserBodyLower⟩ + have hUserPreserves : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some nativeContract) := + hPreserves nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower pre suffix hCases + exact + NativeBlockPreservesWord_switchCaseBody_nonpayable_of_user_body + fn nativeContract reservedNames n0 body' callvalueGuardBody + calldataGuardBody bodyNative bodyStart bodyEnd hNonPayable hBodyLower + hBodyShape hUserPreserves + +private theorem nativeGeneratedSelectorHitBodyPreservesMatched_mappingFree_payable + (tx : IRTransaction) (fn : IRFunction) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat) + (hBodyStraight : + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreePreservableStraightStmts + fn.body) + (hPayable : fn.payable = true) + (hCase : + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body')) + (hBodyLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd)) + (hSwitchFresh : + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' (some nativeContract) := by + let switchId := Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let matchedName := Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName switchId + have hCaseFresh : + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames body' := by + simpa [matchedName] using + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_find_hit_matched_not_mem + switchId tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' hSwitchFresh hCase + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd hPayable hBodyLower with + ⟨guardBody, bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + have hUserFresh : + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative := by + rw [hBodyShape] at hCaseFresh + exact nativeStmtsWriteNames_not_mem_of_two_prefix matchedName + (EvmYul.Yul.Ast.Stmt.Block []) + (EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + guardBody) + bodyNative hCaseFresh + have hUserPreserves : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + matchedName (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts + matchedName (EvmYul.UInt256.ofNat 1) reservedNames userBodyStart + fn.body bodyNative bodyEnd (some nativeContract) hBodyStraight + hUserBodyLower hUserFresh + simpa [matchedName, switchId] using + NativeBlockPreservesWord_switchCaseBody_payable_of_user_body + fn nativeContract reservedNames n0 body' guardBody bodyNative bodyStart + bodyEnd hPayable hBodyLower hBodyShape hUserPreserves + +private theorem nativeGeneratedSelectorHitBodyPreservesMatched_mappingFree_nonpayable + (tx : IRTransaction) (fn : IRFunction) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat) + (hBodyStraight : + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreePreservableStraightStmts + fn.body) + (hNonPayable : fn.payable = false) + (hCase : + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body')) + (hBodyLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd)) + (hSwitchFresh : + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' (some nativeContract) := by + let switchId := Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let matchedName := Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName switchId + have hCaseFresh : + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames body' := by + simpa [matchedName] using + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_find_hit_matched_not_mem + switchId tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' hSwitchFresh hCase + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, userBodyStart, + hBodyShape, hUserBodyLower⟩ + have hUserFresh : + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative := by + rw [hBodyShape] at hCaseFresh + exact nativeStmtsWriteNames_not_mem_of_three_prefix matchedName + (EvmYul.Yul.Ast.Stmt.Block []) + (EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "callvalue" [])) + callvalueGuardBody) + (EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + calldataGuardBody) + bodyNative hCaseFresh + have hUserPreserves : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + matchedName (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts + matchedName (EvmYul.UInt256.ofNat 1) reservedNames userBodyStart + fn.body bodyNative bodyEnd (some nativeContract) hBodyStraight + hUserBodyLower hUserFresh + simpa [matchedName, switchId] using + NativeBlockPreservesWord_switchCaseBody_nonpayable_of_user_body + fn nativeContract reservedNames n0 body' callvalueGuardBody + calldataGuardBody bodyNative bodyStart bodyEnd hNonPayable hBodyLower + hBodyShape hUserPreserves + +private theorem nativeGeneratedSelectorHitBodyPreservesMatched_mappingFree_of_switchFresh + (irContract : IRContract) + (tx : IRTransaction) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreePreservableStraightStmts + fn.body) : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] → + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' (some nativeContract) := by + intro nativeContract fn reservedNames n0 cases' body' bodyStart bodyEnd + _hLowerRuntime hFind hCase hBodyLower hSwitchFresh _pre _suffix _hCases + by_cases hPayable : fn.payable + · exact + nativeGeneratedSelectorHitBodyPreservesMatched_mappingFree_payable + tx fn nativeContract reservedNames n0 cases' body' bodyStart bodyEnd + (hBodyStraight fn hFind) (by simpa using hPayable) hCase hBodyLower + hSwitchFresh + · exact + nativeGeneratedSelectorHitBodyPreservesMatched_mappingFree_nonpayable + tx fn nativeContract reservedNames n0 cases' body' bodyStart bodyEnd + (hBodyStraight fn hFind) (Bool.eq_false_iff.2 hPayable) hCase + hBodyLower hSwitchFresh + +private theorem nativeGeneratedSelectorHitBodyPreservesMatched_mapping_of_switchFresh + (spec : CompilationModel.CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts fn.body) + (hSide : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∀ stmt, stmt ∈ fn.body → + Compiler.Proofs.YulGeneration.Backends.Native.NativePreservableSideConditionForBridgedStraightStmt + stmt) : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] → + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' (some nativeContract) := by + intro nativeContract fn reservedNames n0 cases' body' bodyStart bodyEnd + hLowerRuntime hFind hCase hBodyLower hSwitchFresh _pre _suffix _hCases + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, _nextSwitchId, _hLowerDispatcher, hNativeContract⟩ + subst nativeContract + let switchId := Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let matchedName := Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName switchId + have hCaseFresh : + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames body' := by + simpa [matchedName] using + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_find_hit_matched_not_mem + switchId tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' hSwitchFresh hCase + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd (by simpa using hPayable) + hBodyLower with + ⟨guardBody, bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + have hUserFresh : + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative := by + rw [hBodyShape] at hCaseFresh + exact nativeStmtsWriteNames_not_mem_of_two_prefix matchedName + (EvmYul.Yul.Ast.Stmt.Block []) + (EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + guardBody) + bodyNative hCaseFresh + have hUserPreserves : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + matchedName (EvmYul.UInt256.ofNat 1) bodyNative + (some (nativeContractOfDispatcherWithMapping dispatcher)) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_bridgedStraightStmts + matchedName (EvmYul.UInt256.ofNat 1) reservedNames userBodyStart + fn.body bodyNative bodyEnd (.Block dispatcher) + (hBodyStraight fn hFind) (hSide fn hFind) hUserBodyLower hUserFresh + simpa [matchedName, switchId] using + NativeBlockPreservesWord_switchCaseBody_payable_of_user_body + fn (nativeContractOfDispatcherWithMapping dispatcher) reservedNames n0 + body' guardBody bodyNative bodyStart bodyEnd (by simpa using hPayable) + hBodyLower hBodyShape hUserPreserves + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, userBodyStart, + hBodyShape, hUserBodyLower⟩ + have hUserFresh : + matchedName ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative := by + rw [hBodyShape] at hCaseFresh + exact nativeStmtsWriteNames_not_mem_of_three_prefix matchedName + (EvmYul.Yul.Ast.Stmt.Block []) + (EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "callvalue" [])) + callvalueGuardBody) + (EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + calldataGuardBody) + bodyNative hCaseFresh + have hUserPreserves : + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + matchedName (EvmYul.UInt256.ofNat 1) bodyNative + (some (nativeContractOfDispatcherWithMapping dispatcher)) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_bridgedStraightStmts + matchedName (EvmYul.UInt256.ofNat 1) reservedNames userBodyStart + fn.body bodyNative bodyEnd (.Block dispatcher) + (hBodyStraight fn hFind) (hSide fn hFind) hUserBodyLower hUserFresh + simpa [matchedName, switchId] using + NativeBlockPreservesWord_switchCaseBody_nonpayable_of_user_body + fn (nativeContractOfDispatcherWithMapping dispatcher) reservedNames n0 + body' callvalueGuardBody calldataGuardBody bodyNative bodyStart bodyEnd + hNonPayable hBodyLower hBodyShape hUserPreserves + +/-- Recombine the factored selected user-body execution and preservation +bridges into the existing all-in-one bridge consumed by the dispatcher stack. -/ +private theorem NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_and_preserves + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hExec : + NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived + irContract tx state observableSlots) + (hPreserves : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx) : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower hUserBodyLower + hguards hArgs + rcases hExec nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, hRevive, hProject, hMatch⟩ + refine ⟨final, nativeYul, shared, store, hBody, ?_, hRevive, hProject, + hMatch⟩ + intro pre suffix hCases + exact + hPreserves nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower pre suffix hCases + +/-- Empty selected user bodies preserve the generated matched flag. -/ +private theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_empty_body + (irContract : IRContract) + (tx : IRTransaction) + (hEmpty : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = []) : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart _hLowerRuntime hFind _hCase _hBodyLower + hUserBodyLower _pre _suffix _hCases + have hBody : fn.body = [] := hEmpty fn hFind + simp [hBody] at hUserBodyLower + rcases hUserBodyLower with ⟨rfl, _rfl⟩ + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_nil + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) (some nativeContract) + +/-- Empty selected user bodies discharge the full revived selector-hit user-body +bridge. -/ +private theorem NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_empty_body + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hEmpty : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = []) : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots := by + exact + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_and_preserves + irContract tx state observableSlots + (NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_selected_user_body_exec_only + irContract tx state observableSlots + (NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_empty_body + irContract tx state observableSlots hEmpty)) + (NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_empty_body + irContract tx hEmpty) + +/-- Empty selected user bodies discharge the unified selected-body result +boundary. -/ +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_empty_body + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hEmpty : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = []) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_preserves + irContract tx state observableSlots + (NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_empty_body + irContract tx state observableSlots hEmpty) + (NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_empty_body + irContract tx hEmpty) + +/-- The selected-function-body bridge implies the existing top-level revived +bridge when success guards are supplied by the generated dispatcher prefix. -/ +private theorem NativeGeneratedSelectorHitUserBodyBridgeAtFuelRevived.of_execIRFunction + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hExecBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) + (hguards : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + DispatchGuardsSafe fn tx) + (hArgs : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params.length ≤ tx.args.length) : + NativeGeneratedSelectorHitUserBodyBridgeAtFuelRevived irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower hUserBodyLower + rcases hExecBridge nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower (hguards fn hFind) (hArgs fn hFind) with + ⟨final, nativeYul, shared, store, hBody, hPreserves, hRevive, hProject, + hMatchExec⟩ + refine ⟨final, nativeYul, shared, store, hBody, hPreserves, hRevive, + hProject, ?_⟩ + exact + nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind + (hguards fn hFind) (hArgs fn hFind) hMatchExec + +/-- A revived-state user-body bridge implies the restored projection bridge +used by the generated dispatcher stack. -/ +private theorem NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_revived + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hRevived : + NativeGeneratedSelectorHitUserBodyBridgeAtFuelRevived irContract tx state + observableSlots) : + NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' body' bodyNative bodyStart + bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower hUserBodyLower + rcases hRevived nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower with + ⟨final, nativeYul, shared, store, hBody, hPreserves, hRevive, hProject, + hMatch⟩ + refine ⟨final, nativeYul, hBody, hPreserves, ?_, hMatch⟩ + have hInitialOk : + ∃ initialShared initialStore, + Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) = + EvmYul.Yul.State.Ok initialShared initialStore := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.initialState] + calc + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) + = + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_restoreCallFrame_of_reviveJump_ok + (YulTransaction.ofIR tx) state.storage state.events final + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots)) + [] shared store hRevive hInitialOk + _ = nativeYul := hProject + +/-- A selected-function-body bridge implies the restored projection bridge used +by the generated dispatcher stack, once generated success guards are known. -/ +private theorem NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_execIRFunction + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hExecBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) + (hguards : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + DispatchGuardsSafe fn tx) + (hArgs : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params.length ≤ tx.args.length) : + NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored irContract tx state + observableSlots := + NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_revived + irContract tx state observableSlots + (NativeGeneratedSelectorHitUserBodyBridgeAtFuelRevived.of_execIRFunction + irContract tx state observableSlots hExecBridge hguards hArgs) + +/-- Generic matched-flag preservation for a selected generated selector-hit +body. + +The native switch proof only needs block preservation of the matched flag for +the selected case body. This theorem derives that block preservation from the +native switch freshness predicate plus per-statement preservation for statements +that do not write the matched flag. -/ +theorem nativeGeneratedSelectorHitBodyPreservesMatched_of_fresh + (tx : IRTransaction) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) + (hCase : + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body')) + (hFresh : + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) + (hStmtPreserves : + ∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt (some nativeContract)) : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' (some nativeContract) := by + intro _pre _suffix _hCases + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' (EvmYul.UInt256.ofNat 1) (some nativeContract) + hFresh hCase hStmtPreserves + +/-- Artifact-level selector-hit bridge. + +This is the composable boundary between the dispatcher proof stack and the +future native function-body correctness theorem: once the dispatcher proof +exposes the selected native case body and its lowering evidence, this predicate +asks directly for the final generated `callDispatcher` result match. -/ +private def NativeGeneratedSelectorHitArtifactBridge + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (_n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) + +/-- Dispatcher continuation shape for selected selector-hit artifacts. + +The existing selector-hit dispatcher theorem returns a continuation of this +form after exposing the lowered case body. Keeping the shape named makes the +remaining body proof plumbing explicit: body semantics supplies execution, +preservation, projection, and result matching; the dispatcher continuation +turns those facts into the final generated `callDispatcher` match. -/ +private def NativeGeneratedSelectorHitDispatcherContinuation + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) : Prop := + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) + +/-- Generated-prefix continuation for direct selected user-body execution. + +The direct native function-body bridge produces execution and projection facts +for the lowered `fn.body`. This predicate names the dispatcher-local +continuation that reinstates the generated payable/calldata guard prefix and +turns those body facts into the final generated `callDispatcher` result match. -/ +private def NativeGeneratedSelectorHitUserBodyGeneratedPrefixContinuation + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) : Prop := + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) + +/-- A body bridge plus the matching dispatcher continuation yields the +artifact-level selector-hit bridge. -/ +private theorem NativeGeneratedSelectorHitArtifactBridge.of_body_bridge_and_continuation + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hBodyBridge : + NativeGeneratedSelectorHitBodyBridge irContract tx state + observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + NativeGeneratedSelectorHitDispatcherContinuation irContract tx state + observableSlots nativeContract reservedNames n0 cases' body') : + NativeGeneratedSelectorHitArtifactBridge irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' body' bodyStart bodyEnd + hLowerRuntime hFind hCase hBodyLower + rcases hBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyStart bodyEnd hLowerRuntime hFind hCase hBodyLower with + ⟨final, nativeYul, hBody, hPreserves, hProject, hMatch⟩ + exact + hCont nativeContract fn reservedNames n0 cases' body' bodyStart bodyEnd + hLowerRuntime hFind hCase hBodyLower + final nativeYul hBody hPreserves hProject hMatch + +/-- A user-body bridge plus a generated-prefix continuation yields the +artifact-level selector-hit bridge. + +This theorem is the composition point for the remaining native function-body +correctness theorem: the semantic bridge only has to prove execution and +projection for the direct lowered `fn.body`; the continuation discharges the +generated calldata/value guard prefix and dispatcher switch context. -/ +private theorem NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_and_continuation + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyBridge irContract tx state + observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)) + 1) + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final, [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + NativeGeneratedSelectorHitArtifactBridge irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' body' bodyStart bodyEnd + hLowerRuntime hFind hCase hBodyLower + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd + (by simpa using hPayable) hBodyLower with + ⟨_guardBody, bodyNative, userBodyStart, _hBodyShape, hUserBodyLower⟩ + rcases hUserBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower with + ⟨final, nativeYul, hBody, hPreserves, hProject, hMatch⟩ + exact + hCont nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower final nativeYul hBody hPreserves hProject hMatch + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨_callvalueGuardBody, _calldataGuardBody, bodyNative, userBodyStart, + _hBodyShape, hUserBodyLower⟩ + rcases hUserBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower with + ⟨final, nativeYul, hBody, hPreserves, hProject, hMatch⟩ + exact + hCont nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower final nativeYul hBody hPreserves hProject hMatch + +/-- An exact-fuel user-body bridge plus a generated-prefix continuation yields +the artifact-level selector-hit bridge. + +This is the fuel-aligned companion to +`NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_and_continuation`. +The selected native user-body execution premise uses +`nativeGeneratedSelectorHitUserBodyFuel`, matching the payable/non-payable +generated-prefix split. -/ +private theorem NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_atFuel_and_continuation + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyBridgeAtFuel irContract tx state + observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final, [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + NativeGeneratedSelectorHitArtifactBridge irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' body' bodyStart bodyEnd + hLowerRuntime hFind hCase hBodyLower + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd + (by simpa using hPayable) hBodyLower with + ⟨_guardBody, bodyNative, userBodyStart, _hBodyShape, hUserBodyLower⟩ + rcases hUserBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower with + ⟨final, nativeYul, hBody, hPreserves, hProject, hMatch⟩ + exact + hCont nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower final nativeYul hBody hPreserves hProject hMatch + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨_callvalueGuardBody, _calldataGuardBody, bodyNative, userBodyStart, + _hBodyShape, hUserBodyLower⟩ + rcases hUserBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower with + ⟨final, nativeYul, hBody, hPreserves, hProject, hMatch⟩ + exact + hCont nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower final nativeYul hBody hPreserves hProject hMatch + +/-- An exact-fuel restored-projection user-body bridge plus a generated-prefix +continuation yields the artifact-level selector-hit bridge. + +This is the projection-aligned companion to +`NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_atFuel_and_continuation`: +the direct lowered `fn.body` execution still uses +`nativeGeneratedSelectorHitUserBodyFuel`, while the projected result is the +dispatcher-restored state consumed by the generated `callDispatcher` +continuation. -/ +private theorem NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_atFuel_restored_and_continuation + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored irContract tx state + observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + NativeGeneratedSelectorHitArtifactBridge irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' body' bodyStart bodyEnd + hLowerRuntime hFind hCase hBodyLower + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd + (by simpa using hPayable) hBodyLower with + ⟨_guardBody, bodyNative, userBodyStart, _hBodyShape, hUserBodyLower⟩ + rcases hUserBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower with + ⟨final, nativeYul, hBody, hPreserves, hProject, hMatch⟩ + exact + hCont nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower final nativeYul hBody hPreserves hProject hMatch + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨_callvalueGuardBody, _calldataGuardBody, bodyNative, userBodyStart, + _hBodyShape, hUserBodyLower⟩ + rcases hUserBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower with + ⟨final, nativeYul, hBody, hPreserves, hProject, hMatch⟩ + exact + hCont nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower final nativeYul hBody hPreserves hProject hMatch + +/-- An artifact-level selector-hit bridge is enough to discharge the broad +selector-hit bridge premise used by the current generated-dispatcher +composition theorem. -/ +private theorem NativeGeneratedSelectorHitBridge.of_artifact_bridge + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArtifactBridge : + NativeGeneratedSelectorHitArtifactBridge irContract tx state + observableSlots) : + NativeGeneratedSelectorHitBridge spec selectors irContract tx state + observableSlots := by + intro nativeContract fn hLowerRuntime hFind + let dummyNativeState : EvmYul.Yul.State := + (inferInstance : Inhabited EvmYul.Yul.State).default + let dummyYul : YulResult := + { success := false + returnValue := none + finalStorage := state.storage + finalMappings := Compiler.Proofs.storageAsMappings state.storage + events := state.events } + rcases + nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots nativeContract + fn dummyNativeState dummyYul hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap with + ⟨reservedNames, n0, cases', _midN, body', bodyStart, bodyEnd, + _hLowerCases, hCase, hBodyLower, _hCont⟩ + exact hArtifactBridge nativeContract fn reservedNames n0 cases' body' + bodyStart bodyEnd hLowerRuntime hFind hCase hBodyLower + +/-- Build the selector-hit bridge from a success-only bridge plus the generated +guard-revert theorems. + +The non-payable value guard and calldata-size guard are discharged here. The +remaining bridge premise only has to handle selector hits that are value-safe +and have enough calldata for the selected function parameters. -/ +private theorem NativeGeneratedSelectorHitBridge.of_success_bridge_and_generated_guard_reverts + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hguards : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + DispatchGuardsSafe fn tx) + (hSuccess : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + DispatchGuardsSafe fn tx → + fn.params.length ≤ tx.args.length → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + NativeGeneratedSelectorHitBridge spec selectors irContract tx state + observableSlots := by + intro nativeContract fn hLowerRuntime hFind + by_cases hPayable : fn.payable = true + · have hValue : + fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0 := + Or.inl hPayable + by_cases hArgs : fn.params.length ≤ tx.args.length + · exact hSuccess nativeContract fn hLowerRuntime hFind + (hguards fn hFind) hArgs + · exact + nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots + nativeContract fn hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap (hguards fn hFind) hValue hArgs + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + by_cases hZero : tx.msgValue % Compiler.Constants.evmModulus = 0 + · have hValue : + fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0 := + Or.inr hZero + by_cases hArgs : fn.params.length ≤ tx.args.length + · exact hSuccess nativeContract fn hLowerRuntime hFind + (hguards fn hFind) hArgs + · exact + nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots + nativeContract fn hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap (hguards fn hFind) hValue hArgs + · exact + nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots + nativeContract fn hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap hNonPayable hZero + +/-- Named-predicate form of +`NativeGeneratedSelectorHitBridge.of_success_bridge_and_generated_guard_reverts`. + +This is the preferred composition point for new callers: it keeps the generated +guard-failure split visible while making the remaining success-path bridge a +single reusable predicate. -/ +private theorem NativeGeneratedSelectorHitBridge.of_success_predicate_and_generated_guard_reverts + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hguards : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + DispatchGuardsSafe fn tx) + (hSuccess : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots) : + NativeGeneratedSelectorHitBridge spec selectors irContract tx state + observableSlots := + NativeGeneratedSelectorHitBridge.of_success_bridge_and_generated_guard_reverts + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hguards + (fun nativeContract fn hLowerRuntime hFind hguardsFn hArgs => + hSuccess nativeContract fn hLowerRuntime hFind hguardsFn hArgs) + +/-- Build the selector-hit bridge from a success-only bridge plus generated +guard-revert theorems, requiring only the generated calldata-threshold bound. + +The success branch reconstructs `DispatchGuardsSafe` from the concrete value +and argument checks plus the transaction no-wrap fact. The short-calldata +branch reconstructs it from value safety plus the explicit selected-function +threshold, avoiding a public nonpayable/value guard premise for callers that +only need the generated guard split. -/ +private theorem NativeGeneratedSelectorHitBridge.of_success_predicate_and_generated_guard_reverts_threshold + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hSuccess : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots) : + NativeGeneratedSelectorHitBridge spec selectors irContract tx state + observableSlots := by + intro nativeContract fn hLowerRuntime hFind + by_cases hPayable : fn.payable = true + · have hValue : + fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0 := + Or.inl hPayable + by_cases hArgs : fn.params.length ≤ tx.args.length + · exact hSuccess nativeContract fn hLowerRuntime hFind + (DispatchGuardsSafe.of_value_safe_of_args_le_of_noWrap + fn tx hValue hArgs hNoWrap) hArgs + · exact + nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots + nativeContract fn hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap + (DispatchGuardsSafe.of_value_safe_of_threshold + fn tx hValue (hThreshold fn hFind)) + hValue hArgs + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + by_cases hZero : tx.msgValue % Compiler.Constants.evmModulus = 0 + · have hValue : + fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0 := + Or.inr hZero + by_cases hArgs : fn.params.length ≤ tx.args.length + · exact hSuccess nativeContract fn hLowerRuntime hFind + (DispatchGuardsSafe.of_value_safe_of_args_le_of_noWrap + fn tx hValue hArgs hNoWrap) hArgs + · exact + nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots + nativeContract fn hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap + (DispatchGuardsSafe.of_value_safe_of_threshold + fn tx hValue (hThreshold fn hFind)) + hValue hArgs + · exact + nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots + nativeContract fn hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap hNonPayable hZero + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the remaining selector-hit body bridge. + +This composes the completed generated lowering and selector-miss proof with a +single selector-hit bridge premise. The premise is intentionally narrow: it is +exactly what the future native function-body correctness theorem must supply. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_bridge + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hHitBridge : + NativeGeneratedSelectorHitBridge spec selectors irContract tx state + observableSlots) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + rcases lowerRuntimeContractNative_of_compile_ok_supported_exists + hcompile hSupported with + ⟨nativeContract, hLowerRuntime⟩ + cases hFind : + irContract.functions.find? + (fun fn => fn.selector == tx.functionSelector) with + | none => + exact ⟨nativeContract, hLowerRuntime, + nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots + nativeContract hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap⟩ + | some fn => + exact ⟨nativeContract, hLowerRuntime, + hHitBridge nativeContract fn hLowerRuntime hFind⟩ + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the selected-body artifact bridge. + +This version exposes the next practical proof boundary: selector miss is closed +generically, while selector hits only need a proof for the concrete lowered +case body artifacts produced by the dispatcher lowering stack. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_artifact_bridge + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArtifactBridge : + NativeGeneratedSelectorHitArtifactBridge irContract tx state + observableSlots) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_bridge + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitBridge.of_artifact_bridge + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hArtifactBridge) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the remaining success-only selector-hit bridge. + +Selector miss, non-payable value guard failure, and calldata-size guard failure +are closed generically. The remaining premise only covers selected function +success paths where the generated guards pass. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hguards : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + DispatchGuardsSafe fn tx) + (hSuccess : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_bridge + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitBridge.of_success_predicate_and_generated_guard_reverts + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hguards hSuccess) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the remaining success-only selector-hit bridge and only an explicit +generated calldata-threshold bound. + +Selector miss, non-payable value guard failure, and calldata-size guard failure +are closed generically. Compared with +`nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge`, +this wrapper avoids exposing full `DispatchGuardsSafe` outside the success +branch. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hSuccess : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_bridge + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitBridge.of_success_predicate_and_generated_guard_reverts_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold hSuccess) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile` +for selector-hit success paths that exit through EVMYulLean's halt channel. + +This removes the broad success-bridge premise for `stop`/`return`-style bodies: +callers provide the exact-fuel whole-case halt bridge, and the dispatcher error +channel plus generated guard-revert split complete the native/IR match. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_body_halt_bridge_atFuel + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hHaltBridge : + NativeGeneratedSelectorHitBodyHaltExecBridgeAtFuel irContract tx state + observableSlots) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (NativeGeneratedSelectorHitSuccessBridge.of_body_halt_exec_atFuel + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hHaltBridge) + +/-- Success-only selector-hit adapter from the exact-fuel user-body execution +bridge plus the generated-prefix continuation. + +This is the selected-function version of the older bridge composition: callers +provide guard safety and argument availability for the specific selector hit, +while guard failures are handled by +`NativeGeneratedSelectorHitBridge.of_success_bridge_and_generated_guard_reverts`. +-/ +private theorem nativeGeneratedSelectorHit_success_of_user_body_exec_bridge_atFuel_revived_and_continuation + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) + (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + let dummyNativeState : EvmYul.Yul.State := + (inferInstance : Inhabited EvmYul.Yul.State).default + let dummyYul : YulResult := + { success := false + returnValue := none + finalStorage := state.storage + finalMappings := Compiler.Proofs.storageAsMappings state.storage + events := state.events } + rcases + nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots nativeContract + fn dummyNativeState dummyYul hcompile hLowerRuntime hFind hSelectorRange + hSelectorsRange hNoWrap with + ⟨reservedNames, n0, cases', hCaseMidN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, _hCaseCont⟩ + have hProjectRestored + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (shared : EvmYul.SharedState EvmYul.OperationType.Yul) + (store : EvmYul.Yul.VarStore) + (hRevive : final.reviveJump = EvmYul.Yul.State.Ok shared store) + (hProject : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) = + nativeYul) : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul := by + have hInitialOk : + ∃ initialShared initialStore, + Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) = + EvmYul.Yul.State.Ok initialShared initialStore := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.initialState] + calc + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) + = + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_restoreCallFrame_of_reviveJump_ok + (YulTransaction.ofIR tx) state.storage state.events final + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots)) + [] shared store hRevive hInitialOk + _ = nativeYul := hProject + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd + (by simpa using hPayable) hBodyLower with + ⟨_guardBody, bodyNative, userBodyStart, _hBodyShape, hUserBodyLower⟩ + rcases hUserBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, hPreserves, hRevive, + hProject, hMatchExec⟩ + exact + hCont nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower final nativeYul hBody hPreserves + (hProjectRestored final nativeYul shared store hRevive hProject) + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind + hguards hArgs hMatchExec) + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨_callvalueGuardBody, _calldataGuardBody, bodyNative, userBodyStart, + _hBodyShape, hUserBodyLower⟩ + rcases hUserBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, hPreserves, hRevive, + hProject, hMatchExec⟩ + exact + hCont nativeContract fn reservedNames n0 cases' body' bodyNative + bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase hBodyLower + hUserBodyLower final nativeYul hBody hPreserves + (hProjectRestored final nativeYul shared store hRevive hProject) + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind + hguards hArgs hMatchExec) + +/-- Success-only selector-hit adapter from the exact-fuel user-body execution +bridge, using the generated dispatcher continuation directly. + +The selected body proof first chooses the normal `final/nativeYul` result; the +polymorphic generated success theorem then accepts that result in its +continuation. -/ +private theorem nativeGeneratedSelectorHit_success_of_user_body_exec_bridge_atFuel_revived + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) + (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + rcases + nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_forall_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots nativeContract + fn hcompile hLowerRuntime hFind hSelectorRange hSelectorsRange hNoWrap with + ⟨reservedNames, n0, cases', _midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCaseCont⟩ + have hFuelBound24 : + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length_plus24 + hcompile hSupported hMapping hLowerCases + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length_plus24 + hcompile hSupported hNoMapping hLowerCases + have hProjectRestored + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (shared : EvmYul.SharedState EvmYul.OperationType.Yul) + (store : EvmYul.Yul.VarStore) + (hRevive : final.reviveJump = EvmYul.Yul.State.Ok shared store) + (hProject : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) = + nativeYul) : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul := by + have hInitialOk : + ∃ initialShared initialStore, + Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) = + EvmYul.Yul.State.Ok initialShared initialStore := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.initialState] + calc + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) + = + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_restoreCallFrame_of_reviveJump_ok + (YulTransaction.ofIR tx) state.storage state.events final + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots)) + [] shared store hRevive hInitialOk + _ = nativeYul := hProject + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd + (by simpa using hPayable) hBodyLower with + ⟨guardBody, bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + rcases hUserBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, hPreserves, hRevive, + hProject, hMatchExec⟩ + have hCaseBody : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_payable_prefix_eq + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + guardBody bodyNative nativeContract (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt + fn tx hguards) + (by + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + exact Nat.add_le_add_left hMul 4) + have hFuelEq : + suffix.length + + (1 + (11 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 23)))) = + suffix.length + + (1 + (7 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)))) := by + have hBound23 : cases'.length + 23 ≤ + nativeRuntimeDispatcherFuel irContract := by + omega + omega + simpa [nativeGeneratedSelectorHitUserBodyFuel, hPayable, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, hFuelEq] using + hPrefix.trans (hBody pre suffix hCases) + have hWholePreserves : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract) := by + intro pre suffix hCases + exact + NativeBlockPreservesWord_switchCaseBody_payable_of_user_body + fn nativeContract reservedNames n0 body' guardBody bodyNative + bodyStart bodyEnd (by simpa using hPayable) hBodyLower hBodyShape + (hPreserves pre suffix hCases) + exact + hCaseCont final nativeYul hCaseBody hWholePreserves + (hProjectRestored final nativeYul shared store hRevive hProject) + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind + hguards hArgs hMatchExec) + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, userBodyStart, + hBodyShape, hUserBodyLower⟩ + rcases hUserBodyBridge nativeContract fn reservedNames n0 cases' body' + bodyNative bodyStart bodyEnd userBodyStart hLowerRuntime hFind hCase + hBodyLower hUserBodyLower hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, hPreserves, hRevive, + hProject, hMatchExec⟩ + have hCaseBody : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_nonpayable_prefix_eq + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + callvalueGuardBody calldataGuardBody bodyNative nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + (4 + fn.params.length * 32) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable + fn tx hguards hNonPayable) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt + fn tx hguards) + (by + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + exact Nat.add_le_add_left hMul 4) + have hFuelEq : + suffix.length + + (1 + (12 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 24)))) = + suffix.length + + (1 + (7 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)))) := by + have hBound24 := hFuelBound24 + omega + simpa [nativeGeneratedSelectorHitUserBodyFuel, hNonPayable, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, hFuelEq] using + hPrefix.trans (hBody pre suffix hCases) + have hWholePreserves : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract) := by + intro pre suffix hCases + exact + NativeBlockPreservesWord_switchCaseBody_nonpayable_of_user_body + fn nativeContract reservedNames n0 body' callvalueGuardBody + calldataGuardBody bodyNative bodyStart bodyEnd hNonPayable + hBodyLower hBodyShape (hPreserves pre suffix hCases) + exact + hCaseCont final nativeYul hCaseBody hWholePreserves + (hProjectRestored final nativeYul shared store hRevive hProject) + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind + hguards hArgs hMatchExec) + +/-- The exact-fuel selected user-body execution bridge plus the generated-prefix +continuation supplies the named success-only selector-hit bridge. -/ +private theorem NativeGeneratedSelectorHitSuccessBridge.of_user_body_exec_bridge_atFuel_revived_and_continuation + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots := by + intro nativeContract fn hLowerRuntime hFind hguards hArgs + exact + nativeGeneratedSelectorHit_success_of_user_body_exec_bridge_atFuel_revived_and_continuation + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyBridge hCont + nativeContract fn hLowerRuntime hFind hguards hArgs + +/-- The exact-fuel selected user-body execution bridge supplies the named +success-only selector-hit bridge. -/ +private theorem NativeGeneratedSelectorHitSuccessBridge.of_user_body_exec_bridge_atFuel_revived + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots := by + intro nativeContract fn hLowerRuntime hFind hguards hArgs + exact + nativeGeneratedSelectorHit_success_of_user_body_exec_bridge_atFuel_revived + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyBridge nativeContract fn + hLowerRuntime hFind hguards hArgs + +/-- Direct selected-user-body execution plus switch-local freshness supplies the +named selector-hit success bridge for mapping-free straight bodies. + +This adapter keeps the remaining body-correctness obligation at the direct +`fn.body` execution boundary. Matched-flag preservation is discharged only for +the concrete lowered switch artifacts exposed by the generated dispatcher +theorem, via `nativeGeneratedSelectorHitBodyPreservesMatched_mappingFree_of_switchFresh`; +callers no longer need to provide an arbitrary freshness fact about +`bodyNative`. -/ +private theorem NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_mappingFree_switchFresh + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreePreservableStraightStmts + fn.body) + (hSwitchFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = + .ok (cases', midN) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots := by + intro nativeContract fn hLowerRuntime hFind hguards hArgs + rcases + nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_forall_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots nativeContract + fn hcompile hLowerRuntime hFind hSelectorRange hSelectorsRange hNoWrap with + ⟨reservedNames, n0, cases', _midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCaseCont⟩ + have hFuelBound24 : + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length_plus24 + hcompile hSupported hMapping hLowerCases + · have hNoMapping : irContract.usesMapping = false := + Bool.eq_false_iff.2 hUsesMapping + exact + sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length_plus24 + hcompile hSupported hNoMapping hLowerCases + have hProjectRestored + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (shared : EvmYul.SharedState EvmYul.OperationType.Yul) + (store : EvmYul.Yul.VarStore) + (hRevive : final.reviveJump = EvmYul.Yul.State.Ok shared store) + (hProject : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) = + nativeYul) : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul := by + have hInitialOk : + ∃ initialShared initialStore, + Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) = + EvmYul.Yul.State.Ok initialShared initialStore := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.initialState] + calc + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) + = + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_restoreCallFrame_of_reviveJump_ok + (YulTransaction.ofIR tx) state.storage state.events final + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots)) + [] shared store hRevive hInitialOk + _ = nativeYul := hProject + have hWholePreserves : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract) := by + exact + nativeGeneratedSelectorHitBodyPreservesMatched_mappingFree_of_switchFresh + irContract tx hBodyStraight nativeContract fn reservedNames n0 cases' + body' bodyStart bodyEnd hLowerRuntime hFind hCase hBodyLower + (hSwitchFresh nativeContract reservedNames n0 cases' _midN + hLowerRuntime hLowerCases) + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd + (by simpa using hPayable) hBodyLower with + ⟨guardBody, bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + rcases hUserBodyExec nativeContract fn reservedNames n0 cases' + bodyNative bodyEnd userBodyStart hLowerRuntime hFind hUserBodyLower + hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, hRevive, hProject, + hMatchExec⟩ + have hCaseBody : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_payable_prefix_eq + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + guardBody bodyNative nativeContract (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt + fn tx hguards) + (by + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + exact Nat.add_le_add_left hMul 4) + have hFuelEq : + suffix.length + + (1 + (11 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 23)))) = + suffix.length + + (1 + (7 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)))) := by + have hBound23 : cases'.length + 23 ≤ + nativeRuntimeDispatcherFuel irContract := by + omega + omega + simpa [nativeGeneratedSelectorHitUserBodyFuel, hPayable, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, hFuelEq] using + hPrefix.trans (hBody pre suffix) + exact + hCaseCont final nativeYul hCaseBody hWholePreserves + (hProjectRestored final nativeYul shared store hRevive hProject) + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind + hguards hArgs hMatchExec) + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, userBodyStart, + hBodyShape, hUserBodyLower⟩ + rcases hUserBodyExec nativeContract fn reservedNames n0 cases' + bodyNative bodyEnd userBodyStart hLowerRuntime hFind hUserBodyLower + hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, hRevive, hProject, + hMatchExec⟩ + have hCaseBody : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_nonpayable_prefix_eq + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + callvalueGuardBody calldataGuardBody bodyNative nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + (4 + fn.params.length * 32) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable + fn tx hguards hNonPayable) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt + fn tx hguards) + (by + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + exact Nat.add_le_add_left hMul 4) + have hFuelEq : + suffix.length + + (1 + (12 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 24)))) = + suffix.length + + (1 + (7 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)))) := by + have hBound24 := hFuelBound24 + omega + simpa [nativeGeneratedSelectorHitUserBodyFuel, hNonPayable, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, hFuelEq] using + hPrefix.trans (hBody pre suffix) + exact + hCaseCont final nativeYul hCaseBody hWholePreserves + (hProjectRestored final nativeYul shared store hRevive hProject) + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind + hguards hArgs hMatchExec) + +private theorem NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hMapping : irContract.usesMapping = true) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts fn.body) + (hSide : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∀ stmt, stmt ∈ fn.body → + Compiler.Proofs.YulGeneration.Backends.Native.NativePreservableSideConditionForBridgedStraightStmt + stmt) + (hSwitchFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = + .ok (cases', midN) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots := by + intro nativeContract fn hLowerRuntime hFind hguards hArgs + rcases + nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_forall_of_compile_ok_supported + spec selectors hSupported irContract tx state observableSlots nativeContract + fn hcompile hLowerRuntime hFind hSelectorRange hSelectorsRange hNoWrap with + ⟨reservedNames, n0, cases', _midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hCaseCont⟩ + have hFuelBound24 : + cases'.length + 24 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length_plus24 + hcompile hSupported hMapping hLowerCases + have hProjectRestored + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (shared : EvmYul.SharedState EvmYul.OperationType.Yul) + (store : EvmYul.Yul.VarStore) + (hRevive : final.reviveJump = EvmYul.Yul.State.Ok shared store) + (hProject : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) = + nativeYul) : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul := by + have hInitialOk : + ∃ initialShared initialStore, + Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) = + EvmYul.Yul.State.Ok initialShared initialStore := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.initialState] + calc + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) + = + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final.reviveJump, [])) := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_restoreCallFrame_of_reviveJump_ok + (YulTransaction.ofIR tx) state.storage state.events final + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots)) + [] shared store hRevive hInitialOk + _ = nativeYul := hProject + have hWholePreserves : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract) := by + exact + nativeGeneratedSelectorHitBodyPreservesMatched_mapping_of_switchFresh + spec selectors hSupported irContract tx hcompile hMapping + hBodyStraight hSide nativeContract fn reservedNames n0 cases' + body' bodyStart bodyEnd hLowerRuntime hFind hCase hBodyLower + (hSwitchFresh nativeContract reservedNames n0 cases' _midN + hLowerRuntime hLowerCases) + by_cases hPayable : fn.payable + · rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd + (by simpa using hPayable) hBodyLower with + ⟨guardBody, bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + rcases hUserBodyExec nativeContract fn reservedNames n0 cases' + bodyNative bodyEnd userBodyStart hLowerRuntime hFind hUserBodyLower + hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, hRevive, hProject, + hMatchExec⟩ + have hCaseBody : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_payable_prefix_eq + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + guardBody bodyNative nativeContract (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt + fn tx hguards) + (by + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + exact Nat.add_le_add_left hMul 4) + have hFuelEq : + suffix.length + + (1 + (11 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 23)))) = + suffix.length + + (1 + (7 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)))) := by + have hBound23 : cases'.length + 23 ≤ + nativeRuntimeDispatcherFuel irContract := by + omega + omega + simpa [nativeGeneratedSelectorHitUserBodyFuel, hPayable, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, hFuelEq] using + hPrefix.trans (hBody pre suffix) + exact + hCaseCont final nativeYul hCaseBody hWholePreserves + (hProjectRestored final nativeYul shared store hRevive hProject) + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind + hguards hArgs hMatchExec) + · have hNonPayable : fn.payable = false := Bool.eq_false_iff.2 hPayable + rcases + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, userBodyStart, + hBodyShape, hUserBodyLower⟩ + rcases hUserBodyExec nativeContract fn reservedNames n0 cases' + bodyNative bodyEnd userBodyStart hLowerRuntime hFind hUserBodyLower + hguards hArgs with + ⟨final, nativeYul, shared, store, hBody, hRevive, hProject, + hMatchExec⟩ + have hCaseBody : + ∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final := by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_nonpayable_prefix_eq + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + callvalueGuardBody calldataGuardBody bodyNative nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + (4 + fn.params.length * 32) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable + fn tx hguards hNonPayable) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt + fn tx hguards) + (by + have hMul : fn.params.length * 32 ≤ tx.args.length * 32 := + Nat.mul_le_mul_right 32 hArgs + exact Nat.add_le_add_left hMul 4) + have hFuelEq : + suffix.length + + (1 + (12 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 24)))) = + suffix.length + + (1 + (7 + (nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)))) := by + have hBound24 := hFuelBound24 + omega + simpa [nativeGeneratedSelectorHitUserBodyFuel, hNonPayable, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, hFuelEq] using + hPrefix.trans (hBody pre suffix) + exact + hCaseCont final nativeYul hCaseBody hWholePreserves + (hProjectRestored final nativeYul shared store hRevive hProject) + (nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + irContract tx state observableSlots fn (.ok nativeYul) hFind + hguards hArgs hMatchExec) + +/-- A direct selected-user-body exec-only bridge plus the dispatcher-local +matched-flag preservation bridge supplies the named selector-hit success +bridge. + +This is the narrow success-case boundary for the remaining native +function-body theorem: prove direct execution of the lowered `fn.body` against +`execIRFunction`, while preservation can be discharged independently. -/ +private theorem NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_preserves + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hUserBodyPreserves : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx) : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots := + NativeGeneratedSelectorHitSuccessBridge.of_user_body_exec_bridge_atFuel_revived + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_and_preserves + irContract tx state observableSlots + (NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_selected_user_body_exec_only + irContract tx state observableSlots hUserBodyExec) + hUserBodyPreserves) + +/-- A unified selected-user-body result bridge supplies the named selector-hit +success bridge. + +This is the dispatcher-facing shape for the remaining generic native +function-body theorem: prove either the halt-channel body result or the normal +revived body result plus matched-flag preservation, and the generated prefix +and dispatcher continuation are discharged here. -/ +private theorem NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_result + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyResult : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots) : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots := by + rcases hUserBodyResult with hUserBodyHalt | + ⟨hUserBodyExec, hUserBodyPreserves⟩ + · exact + NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_halt_exec_atFuel + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyHalt + · exact + NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_preserves + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyExec + hUserBodyPreserves + +/-- Empty selected user bodies supply the named selector-hit success bridge +without a native body-execution premise. -/ +private theorem NativeGeneratedSelectorHitSuccessBridge.of_empty_body + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hEmpty : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = []) : + NativeGeneratedSelectorHitSuccessBridge irContract tx state + observableSlots := + NativeGeneratedSelectorHitSuccessBridge.of_user_body_exec_bridge_atFuel_revived + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_empty_body + irContract tx state observableSlots hEmpty) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the exact-fuel lowered-user-body proof stated against +`execIRFunction`, with generated guard failures already discharged. + +Unlike the older +`nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_atFuel_revived_and_continuation`, +this wrapper does not require a global proof that every selector hit has enough +arguments. The argument-availability proof is only required in the success +branch selected after generated guard reverts are split off. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_success_only_atFuel_revived_and_continuation + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (NativeGeneratedSelectorHitSuccessBridge.of_user_body_exec_bridge_atFuel_revived_and_continuation + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyBridge hCont) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the exact-fuel lowered-user-body proof stated against +`execIRFunction`, with generated guard failures already discharged. + +This version consumes the selected user-body execution bridge directly; the +generated dispatcher continuation is provided by +`nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_forall_of_compile_ok_supported`. +-/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_success_only_atFuel_revived + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (NativeGeneratedSelectorHitSuccessBridge.of_user_body_exec_bridge_atFuel_revived + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyBridge) + +/-- Generated `callDispatcher` result theorem for empty selected user bodies. + +This special case consumes no native body-execution premise: empty selected +`fn.body` lowers to a native no-op, preserves the generated matched flag, and +projects to the selected `execIRFunction` result directly. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_empty_selected_body + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hEmpty : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = []) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (NativeGeneratedSelectorHitSuccessBridge.of_empty_body + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hEmpty) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the direct selected-user-body exec-only bridge and dispatcher-local +matched-flag preservation. + +Compared with the older all-in-one user-body bridge wrappers, this theorem +keeps native function-body execution and matched-flag preservation factored so +the final generic body proof can target `execIRFunction` directly. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_preserves + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hUserBodyPreserves : + NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_preserves + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyExec + hUserBodyPreserves) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo direct selected-body execution and mapping-free straight-body closure. + +This routes historical `BridgedStraightStmts` evidence through the actual +runtime mapping-free preservation path, so the dispatcher theorem does not need +callers to first package `NativeMappingFreePreservableStraightStmts` by hand. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts fn.body) + (hMappingFreeSide : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∀ stmt, stmt ∈ fn.body → + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreeSideConditionForBridgedStraightStmt + stmt) + (hFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames bodyNative) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_result + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mappingFree + irContract tx state observableSlots hUserBodyExec hBodyStraight + hMappingFreeSide hFresh)) + +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree_switchFresh + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts fn.body) + (hMappingFreeSide : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∀ stmt, stmt ∈ fn.body → + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreeSideConditionForBridgedStraightStmt + stmt) + (hSwitchFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = + .ok (cases', midN) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_mappingFree_switchFresh + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyExec + (fun fn hFind => + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreePreservableStraightStmts.of_bridgedStraightStmts + (hBodyStraight fn hFind) (hMappingFreeSide fn hFind)) + hSwitchFresh) + +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hMapping : irContract.usesMapping = true) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts fn.body) + (hSide : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∀ stmt, stmt ∈ fn.body → + Compiler.Proofs.YulGeneration.Backends.Native.NativePreservableSideConditionForBridgedStraightStmt + stmt) + (hSwitchFresh : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = + .ok (cases', midN) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyExec hMapping + hBodyStraight hSide hSwitchFresh) + +private theorem nativeGeneratedSwitchTempsFreshForNativeBodies_of_case_body_fresh + (irContract : IRContract) + (hCaseFresh : + ∀ (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) (bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForWrites + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + (Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames + bodyNative)) : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + Compiler.Proofs.YulGeneration.Backends.lowerSwitchCasesNativeWithSwitchIds + reservedNames + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0 + 1) + (Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases + irContract.functions) = + .ok (cases', midN) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] := by + intro nativeContract reservedNames n0 cases' midN _hLowerRuntime hLowerCases + exact + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_buildSwitchSourceCases_of_lowerSwitchCasesNativeWithSwitchIds_of_case_body_fresh + reservedNames n0 midN irContract.functions cases' hLowerCases + (fun fn bodyNative bodyStart bodyEnd hFnMem hLowerBody => + hCaseFresh reservedNames n0 fn bodyNative bodyStart bodyEnd hFnMem + hLowerBody) + +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree_caseFresh + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts fn.body) + (hMappingFreeSide : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∀ stmt, stmt ∈ fn.body → + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreeSideConditionForBridgedStraightStmt + stmt) + (hCaseFresh : + ∀ (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) (bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForWrites + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + (Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames + bodyNative)) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree_switchFresh + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyExec hBodyStraight + hMappingFreeSide + (nativeGeneratedSwitchTempsFreshForNativeBodies_of_case_body_fresh + irContract hCaseFresh) + hThreshold + +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_caseFresh + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyExec : + NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx + state observableSlots) + (hMapping : irContract.usesMapping = true) + (hBodyStraight : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts fn.body) + (hSide : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + ∀ stmt, stmt ∈ fn.body → + Compiler.Proofs.YulGeneration.Backends.Native.NativePreservableSideConditionForBridgedStraightStmt + stmt) + (hCaseFresh : + ∀ (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) (bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + fn ∈ irContract.functions → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (bodyNative, bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForWrites + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + (Compiler.Proofs.YulGeneration.Backends.nativeStmtsWriteNames + bodyNative)) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyExec hMapping + hBodyStraight hSide + (nativeGeneratedSwitchTempsFreshForNativeBodies_of_case_body_fresh + irContract hCaseFresh) + hThreshold + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the unified selected-user-body result bridge. + +This keeps the dispatcher theorem independent of whether the selected lowered +function body exits by `YulHalt` (`stop`/`return`) or returns normally to a +revivable function frame (`leave`). -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyResult : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots) + (hguards : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + DispatchGuardsSafe fn tx) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hguards + (NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_result + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyResult) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the unified selected-user-body result bridge and only the generated +calldata-threshold fact needed by the short-calldata guard branch. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyResult : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_result + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hUserBodyResult) + +/-- Closed generated `callDispatcher` theorem for selected singleton-`stop` +bodies. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_stop_body + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hStop : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_stop_body + irContract tx state observableSlots hStop) + hThreshold + +/-- Public generated `callDispatcher` result theorem from `SupportedSpec + +compile`, modulo the exact-fuel selected user-body halt bridge. + +Selector miss and generated selector-hit guard failures are discharged +internally. For `stop`/`return`-style selected bodies, callers provide the +direct lowered user-body halt execution bridge; the generated prefix, compiled +IR threshold transport, and broad success bridge stay behind private adapters. -/ +theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyHalt : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + rcases + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt + irContract tx state observableSlots hUserBodyHalt) + (fun fn hFind => + generatedFunctionCalldataThreshold_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile fn hFind) with + ⟨nativeContract, _hLower, hMatch⟩ + exact ⟨nativeContract, hMatch⟩ + +/-- Source-level native compiler correctness for the generated native runtime. + +This is the public composition surface over the generated native dispatcher +stack: `SupportedSpec + compile` discharges the lowered native runtime witness +internally, rewrites the projected `EvmYul.Yul.callDispatcher` result to the +canonical `interpretIRRuntimeNative` target, discharges selector miss and +generated selector-hit guard failures internally, and composes the remaining +selected-body halt execution bridge with the source-to-IR compiler theorem. -/ +theorem compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyHalt : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx + (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots) + (hEnv : + Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics spec selectors hSupported tx + initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots) := by + rcases + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx + (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots hcompile hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt + irContract tx (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots hUserBodyHalt) + (fun fn hFind => + generatedFunctionCalldataThreshold_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile fn hFind) with + ⟨nativeContract, hLower, hMatch⟩ + have hEq : + nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots nativeContract = + Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ (sizeOf (Compiler.emitYul irContract).runtimeCode)) + irContract tx + (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots := + nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported + tx (FunctionBody.initialIRStateForTx spec tx initialWorld) observableSlots + nativeContract hcompile hSupported hLower hEnv + rw [hEq] at hMatch + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + spec selectors hSupported irContract tx initialWorld htxNormalized + hcalldataSizeFits hcompile) + hMatch + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the selected-body proof and the dispatcher continuation provider. + +This packages the current final proof boundary in one theorem: selector miss is +closed generically; selector hits require only the native body bridge plus the +continuation shape returned by the dispatcher lowering stack. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_body_bridge_and_continuation + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hBodyBridge : + NativeGeneratedSelectorHitBodyBridge irContract tx state + observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + NativeGeneratedSelectorHitDispatcherContinuation irContract tx state + observableSlots nativeContract reservedNames n0 cases' body') : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_artifact_bridge + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitArtifactBridge.of_body_bridge_and_continuation + irContract tx state observableSlots hBodyBridge hCont) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the direct lowered-user-body proof and generated-prefix continuation. + +This is the narrowest current theorem boundary: selector miss and selector-hit +guard/revert paths are closed generically, and selector-hit success is reduced +to proving native semantics for `lowerStmtsNativeWithSwitchIds ... fn.body`. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_and_continuation + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyBridge irContract tx state + observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - + (cases'.length + 19)) + 1) + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final, [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_artifact_bridge + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_and_continuation + irContract tx state observableSlots hUserBodyBridge hCont) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the exact-fuel lowered-user-body proof and generated-prefix +continuation. + +This is the fuel-aligned successor to +`nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_and_continuation`. +The body bridge and continuation use +`nativeGeneratedSelectorHitUserBodyFuel`, so the remaining proof obligation +matches the payable/non-payable generated-prefix dispatcher lemmas. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_and_continuation + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyBridgeAtFuel irContract tx state + observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok (final, [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_artifact_bridge + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_atFuel_and_continuation + irContract tx state observableSlots hUserBodyBridge hCont) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the exact-fuel lowered-user-body proof at the restored dispatcher +projection boundary. + +This is the projection-aligned successor to +`nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_and_continuation`. +The body bridge and continuation now both project the dispatcher-restored +state, matching the native generated dispatcher proof stack directly. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_restored_and_continuation + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored irContract tx state + observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_artifact_bridge + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_atFuel_restored_and_continuation + irContract tx state observableSlots hUserBodyBridge hCont) + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the exact-fuel lowered-user-body proof at the revived body boundary. + +This wrapper lets the remaining body-semantics theorem target +`final.reviveJump`; the restored dispatcher projection is recovered by +`NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_revived`. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_revived_and_continuation + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyBridgeAtFuelRevived irContract tx state + observableSlots) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_restored_and_continuation + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_revived + irContract tx state observableSlots hUserBodyBridge) + hCont + +/-- Generated `callDispatcher` result theorem from `SupportedSpec + compile`, +modulo the exact-fuel lowered-user-body proof stated against +`execIRFunction`. + +This is the compile-level composition point for the remaining native +function-body theorem: the body theorem may target direct function-body IR +semantics, while this wrapper retargets through the revived/restored dispatcher +projection stack. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_atFuel_revived_and_continuation + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hUserBodyBridge : + NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived irContract tx + state observableSlots) + (hguards : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + DispatchGuardsSafe fn tx) + (hArgs : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params.length ≤ tx.args.length) + (hCont : + ∀ (nativeContract : EvmYul.Yul.Ast.YulContract) (fn : IRFunction) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract → + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) → + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart fn.body = + .ok (bodyNative, bodyEnd) → + ∀ (final : EvmYul.Yul.State) (nativeYul : YulResult), + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block bodyNative) + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) state.storage state.events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) state.storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) (.ok nativeYul) → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract)) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_restored_and_continuation + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_execIRFunction + irContract tx state observableSlots hUserBodyBridge hguards hArgs) + hCont + +attribute [deprecated nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported + (since := "2026-05-07")] + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_success_only_atFuel_revived_and_continuation + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_body_halt_bridge_atFuel + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_body_bridge_and_continuation + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_and_continuation + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_and_continuation + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_restored_and_continuation + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_revived_and_continuation + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_atFuel_revived_and_continuation + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_success_only_atFuel_revived + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_empty_selected_body + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_preserves + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result + +attribute [deprecated compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match + (since := "2026-05-07")] + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_environment + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_globalDefaults + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_environment + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_globalDefaults + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_environment + compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_globalDefaults + +attribute [deprecated nativeGeneratedCallDispatcherResultOf + (since := "2026-05-07")] + nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported + nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported_except_mapping_writes_stmt_safety + +/-- Selector-hit error lowered-runtime wrapper with generated function selector +ranges derived from the source selector list. The selected-body +execution/projection/result-match obligations remain explicit. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime_selectors_range + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract)) := + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract fn err nativeYul htxNormalized hcalldataSizeFits hcompile + hLowerRuntime hFind hSelectorRange hNoWrap + (generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange) + +/-- Selector-hit error lowered-runtime wrapper with both the selected +transaction selector range and generated function selector ranges derived from +the source selector list. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime_source_selectors_range + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract)) := + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime_selectors_range + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract fn err nativeYul htxNormalized hcalldataSizeFits hcompile + hLowerRuntime hFind + (selectedGeneratedFunctionSelectorRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange hFind) + hSelectorsRange hNoWrap + +/-- Selector-hit error lowered-runtime wrapper deriving calldata no-wrap from +the transaction calldata-size fit premise. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime_source_selectors_range_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract)) := + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime_source_selectors_range + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract fn err nativeYul htxNormalized hcalldataSizeFits hcompile + hLowerRuntime hFind hSelectorsRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) + +/-- Block-preservation variant of +`compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical`. -/ +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_preserved + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + .ok ()) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) body' + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + have hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = + .ok (nativeContractOfDispatcherWithMapping [.Block inner]) := by + rw [lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + hcompile hSupported hMapping] + rw [hLowerDispatcher] + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds_atFuel + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + initialState observableSlots inner nextSwitchId functions fn final nativeYul + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping + (by simpa [reservedNames] using hLowerCases) + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro hBody hPreservesMatched hProject hMatch + have hNativeDispatcherExec' : + nativeDispatcherExecMatchesIRPositive (nativeRuntimeDispatcherFuel irContract) + irContract tx initialState observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + refine hNativeDispatcherExec hFuel ?_ ?_ ?_ hMatch + · simpa [initialState, reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hBody + · simpa [reservedNames, nativeContractOfDispatcherWithMapping, functions] + using hPreservesMatched + · simpa [initialState, nativeContractOfDispatcherWithMapping, functions] + using hProject + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported + (fuel' := nativeRuntimeDispatcherFuel irContract) + (spec := model) (selectors := selectors) (irContract := irContract) + (tx := tx) (state := initialState) + (observableSlots := observableSlots) + (nativeContract := nativeContractOfDispatcherWithMapping [.Block inner]) + hcompile hSupported hLowerRuntime hEnv + (by + simpa [nativeContractOfDispatcherWithMapping, functions] + using hNativeDispatcherExec')) + +/-- Direct `callDispatcher` mapping selector-hit success theorem at canonical +generated-runtime fuel, using the block-preservation obligation for the +selected native body. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_mapping_canonical_preserved + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) body' + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]))) := by + let initialState := FunctionBody.initialIRStateForTx model tx initialWorld + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + let functions := + ((∅ : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap).insert + "mappingSlot" + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition) + rcases + nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds_atFuel + (nativeRuntimeDispatcherFuel irContract) reservedNames 0 irContract tx + initialState observableSlots inner nextSwitchId functions fn final nativeYul + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange with + ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, hNativeDispatcherExec⟩ + have hFuel : + cases'.length + 19 ≤ nativeRuntimeDispatcherFuel irContract := by + dsimp [nativeRuntimeDispatcherFuel] + exact + sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length + hcompile hSupported hMapping + (by simpa [reservedNames] using hLowerCases) + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, ?_, ?_⟩ + · simpa [reservedNames] using hBodyLower + · intro hBody hPreservesMatched hProject hMatch + have hGeneratedMatch : + nativeGeneratedCallDispatcherMatchesIROn irContract tx initialState + observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]) := by + apply nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + simpa [nativeGeneratedDispatcherExecMatchesIROn, + nativeDispatcherExecMatchesIRPositive, nativeRuntimeDispatcherFuel, + nativeContractOfDispatcherWithMapping, functions] using + hNativeDispatcherExec hFuel + (by simpa [initialState, reservedNames, + nativeContractOfDispatcherWithMapping, functions] using hBody) + (by simpa [reservedNames, nativeContractOfDispatcherWithMapping, + functions] using hPreservesMatched) + (by simpa [initialState, nativeContractOfDispatcherWithMapping, + functions] using hProject) + hMatch + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := hGeneratedMatch) + +/-- Direct `callDispatcher` selector-hit success theorem from successful +lowering of the whole emitted runtime, using a block-preservation obligation +for the selected native body. + +This is the lowered-runtime counterpart of the no-mapping and mapping +`*_canonical_preserved` wrappers: callers no longer expose the concrete +dispatcher lowering or mapping-helper branch, but still provide the selected +body execution/projection/result-match evidence. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_preserved_lowered_runtime + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract)) := by + by_cases hUsesMapping : irContract.usesMapping + · have hMapping : irContract.usesMapping = true := by + simpa using hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved + hcompile hSupported hMapping hLowerRuntime with + ⟨dispatcher, nextSwitchId, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 irContract.functions dispatcher nextSwitchId hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_mapping_canonical_preserved + model selectors hSupported irContract tx initialWorld observableSlots + inner nextSwitchId fn final nativeYul htxNormalized hcalldataSizeFits + hcompile hMapping hLowerBlock hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨switchStart, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + refine ⟨ + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode, + switchStart, cases', body', bodyStart, bodyEnd, hCase, hBodyLower, ?_⟩ + intro hBody hPreserves hProject hMatch + exact hCont hBody hPreserves hProject hMatch + · have hNoMapping : irContract.usesMapping = false := by + exact Bool.eq_false_iff.2 hUsesMapping + rcases lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher + hcompile hSupported hNoMapping hLowerRuntime with + ⟨dispatcher, hLowerDispatcher, hNativeContract⟩ + rcases + lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block + irContract.functions dispatcher hLowerDispatcher with + ⟨inner, hDispatcher, hLowerBlock⟩ + subst nativeContract + subst dispatcher + rcases + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_noMapping_canonical_preserved + model selectors hSupported irContract tx initialWorld observableSlots + inner fn final nativeYul htxNormalized hcalldataSizeFits hcompile + hNoMapping hLowerBlock hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + exact ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + +/-- Direct `callDispatcher` selector-hit success theorem from successful +lowering of the whole emitted runtime, deriving selected-body block preservation +from native switch freshness and per-statement preservation. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract)) := by + rcases + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_preserved_lowered_runtime + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract fn final nativeYul htxNormalized hcalldataSizeFits + hcompile hLowerRuntime hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, ?_⟩ + intro hFresh hBody hStmtPreserves hProject hMatch + exact + hCont hBody + (by + intro pre suffix hcases + exact + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' (EvmYul.UInt256.ofNat 1) (some nativeContract) + hFresh hCase hStmtPreserves) + hProject hMatch + +/-- Selector-hit success lowered-runtime wrapper with generated function +selector ranges derived from the source selector list. This keeps native switch +freshness, selected-body execution, per-statement preservation, projection, and +IR/native result matching as the remaining explicit hit-path obligations. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime_selectors_range + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract)) := + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract fn final nativeYul htxNormalized hcalldataSizeFits hcompile + hLowerRuntime hFind hSelectorRange hNoWrap + (generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange) + +/-- Selector-hit success lowered-runtime wrapper with both selector range facts +derived from the source selector list. The selected-body execution, +preservation, projection, and IR/native result match remain explicit. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime_source_selectors_range + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract)) := + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime_selectors_range + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract fn final nativeYul htxNormalized hcalldataSizeFits hcompile + hLowerRuntime hFind + (selectedGeneratedFunctionSelectorRange_of_compile_ok_supported + hcompile hSupported hSelectorsRange hFind) + hSelectorsRange hNoWrap + +/-- Selector-hit success lowered-runtime wrapper deriving calldata no-wrap from +the transaction calldata-size fit premise. The selected-body execution, +preservation, projection, and IR/native result match remain explicit. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime_source_selectors_range_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hLowerRuntime : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt + (some nativeContract)) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract)) := + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime_source_selectors_range + model selectors hSupported irContract tx initialWorld observableSlots + nativeContract fn final nativeYul htxNormalized hcalldataSizeFits hcompile + hLowerRuntime hFind hSelectorsRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) + +/-- Direct `callDispatcher` mapping selector-hit success theorem at canonical +generated-runtime fuel, deriving selected-body block preservation from native +switch freshness and per-statement preservation. -/ +private theorem compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_mapping_canonical + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) stmt + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots + (nativeContractOfDispatcherWithMapping [.Block inner]))) := by + let reservedNames := + Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode + rcases + compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_mapping_canonical_preserved + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId fn final nativeYul htxNormalized hcalldataSizeFits hcompile + hMapping hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange with + ⟨switchStart, cases', body', bodyStart, bodyEnd, hCase, hBodyLower, + hPreserved⟩ + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, hCase, hBodyLower, ?_⟩ + intro hFresh hBody hStmtPreserves hProject hMatch + exact hPreserved hBody + (fun pre suffix hcases => + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames switchStart) + tx.functionSelector tx.functionSelector body' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt] + cases' (EvmYul.UInt256.ofNat 1) + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (by simpa [reservedNames] using hFresh) hCase + (by + simpa [reservedNames, nativeContractOfDispatcherWithMapping] using + hStmtPreserves)) + hProject hMatch + +private theorem compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := + compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner + htxNormalized hcalldataSizeFits hcompile hNoMapping hLowerDispatcher hFind + hSelectorRange hNoWrap hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := + compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner + htxNormalized hcalldataSizeFits hcompile hNoMapping hLowerDispatcher hFind + hSelectorRange hNoWrap hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical_ofIR_environment_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := + compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical_ofIR_environment + model selectors hSupported irContract tx initialWorld observableSlots inner + htxNormalized hcalldataSizeFits hcompile hNoMapping hLowerDispatcher hFind + hSelectorRange (txNoWrap_of_calldataSizeFits hcalldataSizeFits) + hFunctionSelectorsRange hChainId hBlobBaseFee hNoHeader + +private theorem compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical_ofIR_globalDefaults_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := + compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical_ofIR_globalDefaults + model selectors hSupported irContract tx initialWorld observableSlots inner + htxNormalized hcalldataSizeFits hcompile hNoMapping hLowerDispatcher hFind + hSelectorRange (txNoWrap_of_calldataSizeFits hcalldataSizeFits) + hFunctionSelectorsRange hChainId hBlobBaseFee hNoHeader + +private theorem compile_preserves_native_evmYulLean_selector_miss_mapping_canonical_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := + compile_preserves_native_evmYulLean_selector_miss_mapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId htxNormalized hcalldataSizeFits hcompile hMapping + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_miss_mapping_canonical_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := + compile_preserves_native_evmYulLean_selector_miss_mapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId htxNormalized hcalldataSizeFits hcompile hMapping + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_miss_mapping_canonical_ofIR_environment_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := + compile_preserves_native_evmYulLean_selector_miss_mapping_canonical_ofIR_environment + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId htxNormalized hcalldataSizeFits hcompile hMapping + hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) hFunctionSelectorsRange + hChainId hBlobBaseFee hNoHeader + +private theorem compile_preserves_native_evmYulLean_selector_miss_mapping_canonical_ofIR_globalDefaults_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + none) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots) := + compile_preserves_native_evmYulLean_selector_miss_mapping_canonical_ofIR_globalDefaults + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId htxNormalized hcalldataSizeFits hcompile hMapping + hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) hFunctionSelectorsRange + hChainId hBlobBaseFee hNoHeader + +private theorem compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner fn + err nativeYul htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner fn + err nativeYul htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hFind hSelectorRange hNoWrap hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical_ofIR_environment_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical_ofIR_environment + model selectors hSupported irContract tx initialWorld observableSlots inner fn + err nativeYul htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) hFunctionSelectorsRange + hChainId hBlobBaseFee hNoHeader + +private theorem compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical_ofIR_globalDefaults_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical_ofIR_globalDefaults + model selectors hSupported irContract tx initialWorld observableSlots inner fn + err nativeYul htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) hFunctionSelectorsRange + hChainId hBlobBaseFee hNoHeader + +private theorem compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId fn err nativeYul htxNormalized hcalldataSizeFits hcompile + hMapping hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId fn err nativeYul htxNormalized hcalldataSizeFits hcompile + hMapping hLowerDispatcher hFind hSelectorRange hNoWrap + hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical_ofIR_environment_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical_ofIR_environment + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId fn err nativeYul htxNormalized hcalldataSizeFits hcompile + hMapping hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) hFunctionSelectorsRange + hChainId hBlobBaseFee hNoHeader + +private theorem compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical_ofIR_globalDefaults_calldata_size_fits + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .error err) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.error err) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical_ofIR_globalDefaults + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId fn err nativeYul htxNormalized hcalldataSizeFits hcompile + hMapping hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) hFunctionSelectorsRange + hChainId hBlobBaseFee hNoHeader + +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner fn + final nativeYul htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner fn + final nativeYul htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_preserved_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_preserved + model selectors hSupported irContract tx initialWorld observableSlots inner fn + final nativeYul htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_preserved_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNoMapping : irContract.usesMapping = false) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok [.Block inner]) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcher [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' + (some (nativeContractOfDispatcher [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcher [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_preserved + model selectors hSupported irContract tx initialWorld observableSlots inner fn + final nativeYul htxNormalized hcalldataSizeFits hcompile hNoMapping + hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) stmt + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId fn final nativeYul htxNormalized hcalldataSizeFits hcompile + hMapping hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) + hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((Compiler.Proofs.YulGeneration.Backends.nativeSwitchTempsFreshForNativeBodies + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) cases' + [Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt]) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ stmt, stmt ∈ body' → + Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) ∉ + Compiler.Proofs.YulGeneration.Backends.nativeStmtWriteNames stmt → + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) stmt + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId fn final nativeYul htxNormalized hcalldataSizeFits hcompile + hMapping hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) + hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_preserved_ofIR_environment + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) body' + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_preserved + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId fn final nativeYul htxNormalized hcalldataSizeFits hcompile + hMapping hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) + hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +private theorem compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_preserved_ofIR_globalDefaults + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (inner : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat) + (fn : IRFunction) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hMapping : irContract.usesMapping = true) + (hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok ([.Block inner], nextSwitchId)) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ irContract.functions → fn.selector < EvmYul.UInt256.size) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + cases'.find? (fun entry => entry.1 == tx.functionSelector) = + some (tx.functionSelector, body') ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) bodyStart + (Compiler.Proofs.YulGeneration.Backends.Native.switchCaseBody fn) = + .ok (body', bodyEnd) ∧ + ((∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + EvmYul.Yul.exec + (((nativeRuntimeDispatcherFuel irContract - (cases'.length + 19)) + + 1) + suffix.length + 7) (.Block body') + (some (nativeContractOfDispatcherWithMapping [.Block inner])) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots) + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart) + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore) = + .ok final) → + (∀ pre suffix, + cases' = pre ++ (tx.functionSelector, body') :: suffix → + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord + (Compiler.Proofs.YulGeneration.Backends.nativeSwitchMatchedTempName + (Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + switchStart)) + (EvmYul.UInt256.ofNat 1) body' + (some (nativeContractOfDispatcherWithMapping [.Block inner]))) → + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (FunctionBody.initialIRStateForTx model tx initialWorld).events + (.ok + (((final.reviveJump.overwrite? + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))).setStore + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + (nativeContractOfDispatcherWithMapping [.Block inner]) + (YulTransaction.ofIR tx) + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + (Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots))), [])) = + nativeYul → + nativeResultsMatchOn observableSlots + (interpretIR irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld)) + (.ok nativeYul) → + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (nativeRuntimeFuel irContract) irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots)) := + compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_preserved + model selectors hSupported irContract tx initialWorld observableSlots inner + nextSwitchId fn final nativeYul htxNormalized hcalldataSizeFits hcompile + hMapping hLowerDispatcher hFind hSelectorRange + (txNoWrap_of_calldataSizeFits hcalldataSizeFits) + hFunctionSelectorsRange + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + +/-- Deprecated compatibility wrapper over the direct projected +`EvmYul.Yul.callDispatcher` result for the generated runtime, from the legacy +canonical generated dispatcher-exec match target. + +New code should prove the direct `nativeGeneratedCallDispatcherResultOf` result +and use `compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match`. +-/ +@[deprecated compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match + (since := "2026-05-07")] +private theorem compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) (irContract : IRContract) + (tx : IRTransaction) (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (hNativeDispatcherExec : + nativeGeneratedDispatcherExecMatchesIROn irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots nativeContract) := by + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + (hSourceIR := + Compiler.Proofs.IRGeneration.Contract.compile_preserves_semantics + model selectors hSupported irContract tx initialWorld + htxNormalized hcalldataSizeFits hcompile) + (hNativeIR := + nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + hNativeDispatcherExec) + +/-- Deprecated helper-free generated dispatcher wrapper over concrete +dispatcher lowering, with the legacy canonical generated dispatcher-exec native +premise. + +New code should target the concrete `nativeGeneratedCallDispatcherResultOf` +result directly via +`compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match`. +-/ +@[deprecated compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match + (since := "2026-05-07")] +private theorem compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (_hNoMapping : irContract.usesMapping = false) + (_hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hNativeDispatcherExec : + nativeGeneratedDispatcherExecMatchesIROn irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeGeneratedDispatcherContractOf dispatcher)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeGeneratedDispatcherContractOf dispatcher)) := by + exact + compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match + model selectors hSupported irContract tx initialWorld observableSlots + (nativeGeneratedDispatcherContractOf dispatcher) htxNormalized + hcalldataSizeFits hcompile + (nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + hNativeDispatcherExec) + +/-- Deprecated mapping-helper generated dispatcher wrapper over concrete +dispatcher lowering, with the legacy canonical generated dispatcher-exec native +premise. + +New code should target the concrete `nativeGeneratedCallDispatcherResultOf` +result directly via +`compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match`. +-/ +@[deprecated compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match + (since := "2026-05-07")] +private theorem compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping + (model : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hcompile : CompilationModel.compile model selectors = Except.ok irContract) + (_hMapping : irContract.usesMapping = true) + (_hLowerDispatcher : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hNativeDispatcherExec : + nativeGeneratedDispatcherExecMatchesIROn irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots (nativeGeneratedDispatcherContractWithMappingOf dispatcher)) : + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics model selectors hSupported tx initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx model tx initialWorld) + observableSlots + (nativeGeneratedDispatcherContractWithMappingOf dispatcher)) := by + exact + compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match + model selectors hSupported irContract tx initialWorld observableSlots + (nativeGeneratedDispatcherContractWithMappingOf dispatcher) htxNormalized + hcalldataSizeFits hcompile + (nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec + hNativeDispatcherExec) + +/-- Supported compiler-produced projected-result theorem on the direct +native-vs-IR target. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_match + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure + hCompile hSupported hStaticParams hSafeBodies hLower hEnv hProject hMatch + +/-- Supported compiler-produced positive dispatcher-exec theorem on the direct +native-vs-IR target, with source-level body closure named explicitly. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots nativeContract) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_match + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hStaticParams hSafeBodies hLower hEnv hNativeDispatcherExec + +/-- Supported compiler-produced positive dispatcher-exec theorem with +`YulTransaction.ofIR` environment validation discharged from representable +environment facts. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots nativeContract) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeDispatcherExec + +/-- Supported compiler-produced positive dispatcher-exec theorem with +`YulTransaction.ofIR` environment validation discharged from the EVMYulLean +global default environment. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots nativeContract) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeDispatcherExec + +/-- Supported no-mapping compiler-produced positive dispatcher-statement theorem +on the direct native-vs-IR target, with `YulTransaction.ofIR` environment +validation discharged from representable environment facts. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hNativeDispatcherExec + +/-- Supported no-mapping compiler-produced positive dispatcher-statement theorem +on the direct native-vs-IR target, with `YulTransaction.ofIR` environment +validation discharged from the EVMYulLean global default environment. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hNativeDispatcherExec + +/-- Supported compiler-produced projected-result theorem on the direct +native-vs-IR target, with source-level body closure named explicitly. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_match + fuel' spec selectors irContract tx initialState observableSlots nativeContract nativeYul + hCompile hSupported hStaticParams hSafeBodies hLower hEnv hProject hMatch + +/-- Supported compiler-produced projected-result theorem with +`YulTransaction.ofIR` environment validation discharged from representable +environment facts. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure + fuel' spec selectors irContract tx initialState observableSlots nativeContract nativeYul + hCompile hSupported hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +/-- Supported compiler-produced projected-result theorem with +`YulTransaction.ofIR` environment validation discharged from the EVMYulLean +global default environment. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots nativeContract nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure + fuel' spec selectors irContract tx initialState observableSlots nativeContract nativeYul + hCompile hSupported hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +/-- Supported no-mapping compiler-produced projected-result +dispatcher-statement theorem on the direct native-vs-IR target, with +`YulTransaction.ofIR` environment validation discharged from representable +environment facts. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hProject hMatch + +/-- Supported no-mapping compiler-produced projected-result +dispatcher-statement theorem on the direct native-vs-IR target, with +`YulTransaction.ofIR` environment validation discharged from the EVMYulLean +global default environment. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hProject hMatch + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hNativeDispatcherExec + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hNativeDispatcherExec + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hProject hMatch + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (dispatcher : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLowerDispatcher : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId)) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults + hCompile hSupported hMapping hStaticParams hSafeBodies hLowerDispatcher + hChainId hBlobBaseFee hNoHeader hProject hMatch + +/-- Supported compiler-produced Layers 2+3 theorem for no-mapping full runtime +lowering, exposing the concrete dispatcher-statement lowering internally. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLower hEnv + hNativeDispatcherExec + +/-- Supported compiler-produced Layers 2+3 theorem for no-mapping projected +full runtime lowering, exposing the concrete dispatcher-statement lowering +internally. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hNoMapping hStaticParams hSafeBodies hLower + hEnv hProject hMatch + +/-- Supported compiler-produced Layers 2+3 theorem for mapping-helper full +runtime lowering, exposing the concrete reserved dispatcher-statement lowering +internally. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hMapping hStaticParams hSafeBodies hLower hEnv + hNativeDispatcherExec + +/-- Supported compiler-produced Layers 2+3 theorem for mapping-helper projected +full runtime lowering, exposing the concrete reserved dispatcher-statement +lowering internally. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hMapping hStaticParams hSafeBodies hLower hEnv + hProject hMatch + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hNoMapping hLower hEnv hNativeDispatcherExec + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hNoMapping hLower hEnv hProject hMatch + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hNativeDispatcherExec : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hMapping hLower hEnv hNativeDispatcherExec + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hEnv : Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = .ok ()) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hMapping hLower hEnv hProject hMatch + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hNoMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeDispatcherExec + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hNoMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeDispatcherExec + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hNoMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hNoMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeDispatcherExec + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeDispatcherExec + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hMapping hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +/-- Supported compiler-produced Layers 2+3 theorem for no-mapping full runtime +lowering, with `YulTransaction.ofIR` environment validation discharged from +representable environment facts. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeDispatcherExec + +/-- Supported compiler-produced Layers 2+3 theorem for no-mapping full runtime +lowering, with `YulTransaction.ofIR` environment validation discharged from +the EVMYulLean global default environment. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hNoMapping hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeDispatcherExec + +/-- Supported compiler-produced Layers 2+3 projected-result theorem for +no-mapping full runtime lowering, with `YulTransaction.ofIR` environment +validation discharged from representable environment facts. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hNoMapping hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +/-- Supported compiler-produced Layers 2+3 projected-result theorem for +no-mapping full runtime lowering, with `YulTransaction.ofIR` environment +validation discharged from the EVMYulLean global default environment. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hNoMapping : irContract.usesMapping = false) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ dispatcher : List EvmYul.Yul.Ast.Stmt, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok dispatcher → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcher dispatcher) nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hNoMapping hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +/-- Supported compiler-produced Layers 2+3 theorem for mapping-helper full +runtime lowering, with `YulTransaction.ofIR` environment validation discharged +from representable environment facts. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : + Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : + Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hMapping hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeDispatcherExec + +/-- Supported compiler-produced Layers 2+3 theorem for mapping-helper full +runtime lowering, with `YulTransaction.ofIR` environment validation discharged +from the EVMYulLean global default environment. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hNativeDispatcherExec : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeDispatcherExecMatchesIRPositive fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + hCompile hSupported hMapping hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hNativeDispatcherExec + +/-- Supported compiler-produced Layers 2+3 projected-result theorem for +mapping-helper full runtime lowering, with `YulTransaction.ofIR` environment +validation discharged from representable environment facts. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : Compiler.Proofs.YulGeneration.Backends.Native.nativeChainIdRepresentable + tx.chainId = true) + (hBlobBaseFee : Compiler.Proofs.YulGeneration.Backends.Native.nativeBlobBaseFeeRepresentable + tx.blobBaseFee = true) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hMapping hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +/-- Supported compiler-produced Layers 2+3 projected-result theorem for +mapping-helper full runtime lowering, with `YulTransaction.ofIR` environment +validation discharged from the EVMYulLean global default environment. -/ +private theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults + (fuel' : Nat) (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (irContract : IRContract) (tx : IRTransaction) (initialState : IRState) + (observableSlots : List Nat) (nativeContract : EvmYul.Yul.Ast.YulContract) + (nativeYul : YulResult) + (hCompile : CompilationModel.compile spec selectors = .ok irContract) + (hSupported : SupportedSpec spec selectors) + (hMapping : irContract.usesMapping = true) + (hStaticParams : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.AllStaticScalarParams entry.1.params) + (hSafeBodies : ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + Compiler.Proofs.YulGeneration.Backends.BridgedSafeStmts + spec.fields spec.errors .calldata [] false entry.1.body) + (hLower : Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + (Compiler.emitYul irContract).runtimeCode (YulTransaction.ofIR tx) = + false) + (hProject : ∀ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + (Compiler.emitYul irContract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch irContract.functions none none] = + .ok (dispatcher, nextSwitchId) → + nativeProjectedDispatcherResultEq fuel' irContract tx initialState + observableSlots (nativeContractOfDispatcherWithMapping dispatcher) + nativeYul) + (hMatch : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (.ok nativeYul)) : + nativeResultsMatchOn observableSlots (interpretIR irContract tx initialState) + (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative + (Nat.succ fuel') irContract tx initialState observableSlots) := + layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved + fuel' spec selectors irContract tx initialState observableSlots nativeContract + nativeYul hCompile hSupported hMapping hStaticParams hSafeBodies hLower + (Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults + (Compiler.emitYul irContract).runtimeCode tx hChainId hBlobBaseFee + hNoHeader) + hProject hMatch + +/-! ## Concrete Instantiation: SimpleStorage -/ + +/-- The concrete SimpleStorage IR fixture uses only EVMYulLean-bridged Yul +shapes: calldata parameter loading, one literal-slot storage write, one memory +write from `sload`, and `stop`/`return` terminators. -/ +private theorem simpleStorage_functions_bridged : + ∀ fn, fn ∈ simpleStorageIRContract.functions → + Compiler.Proofs.YulGeneration.Backends.BridgedStmts fn.body := by + intro fn hmem + simp [simpleStorageIRContract] at hmem + rcases hmem with rfl | rfl + · apply Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_let + · exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.call + "calldataload" [Yul.YulExpr.lit 4] + (by + left + simp [Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins]) + (by + intro arg harg + simp at harg + subst arg + exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit 4) + · apply Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_sstore_lit + · exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.ident "value" + · exact Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_stop + · apply Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_mstore + · exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit 0 + · exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.call + "sload" [Yul.YulExpr.lit 0] + (by + left + simp [Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins]) + (by + intro arg harg + simp at harg + subst arg + exact Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit 0) + · exact Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_return + (Yul.YulExpr.lit 0) (Yul.YulExpr.lit 32) + (Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit 0) + (Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit 32) + +private theorem simpleStorage_functions_loop_free : + ∀ fn, fn ∈ simpleStorageIRContract.functions → + yulStmtsLoopFree fn.body = true := by + intro fn hmem + simp [simpleStorageIRContract] at hmem ⊢ + rcases hmem with rfl | rfl <;> rfl + +/-- The emitted SimpleStorage runtime consists of the single generated external +dispatcher shell for the two concrete SimpleStorage functions. + +This pins down the outer runtime layer that the native dispatcher bridge must +peel before applying the concrete lowered selector-switch lemmas. -/ +private theorem simpleStorage_runtimeCode_eq_single_dispatcher : + (Compiler.emitYul simpleStorageIRContract).runtimeCode = + [Compiler.CodegenCommon.buildSwitch + simpleStorageIRContract.functions none none] := by + dsimp [Compiler.emitYul, Compiler.CodegenCommon.emitYul, + Compiler.runtimeCode, Compiler.CodegenCommon.runtimeCode, + simpleStorageIRContract] + +private theorem lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative + (stmt : Yul.YulStmt) + (hNoFunc : ∀ name params rets body, + stmt ≠ Yul.YulStmt.funcDef name params rets body) : + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative [stmt] = + match Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative [stmt] with + | .ok dispatcher => + .ok { dispatcher := .Block dispatcher + functions := + (∅ : + Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) } + | .error err => .error err := + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative + stmt hNoFunc + +private noncomputable def simpleStorageNativeDispatcherStmts : + List EvmYul.Yul.Ast.Stmt := + match + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch + simpleStorageIRContract.functions none none] with + | .ok stmts => stmts + | .error _ => [] + +/-- The executable SimpleStorage native witness is exactly the statement +lowering of the single emitted dispatcher shell. + +This exposes the concrete lowered dispatcher block without unfolding the +computed native witness in later selector-case proofs. -/ +private theorem simpleStorageNativeContract_dispatcher_eq_lowered_stmts : + Compiler.SimpleStorageNativeWitness.nativeContract.dispatcher = + .Block simpleStorageNativeDispatcherStmts := by + unfold Compiler.SimpleStorageNativeWitness.nativeContract + rw [simpleStorage_runtimeCode_eq_single_dispatcher] + rw [lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative] + · cases hLower : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch + simpleStorageIRContract.functions none none] with + | ok stmts => + simp [simpleStorageNativeDispatcherStmts, hLower] + | error err => + simp [simpleStorageNativeDispatcherStmts, hLower] + · intro name params rets body h + cases h + +/-- A `.block` head in the native lowering surfaces as a singleton `.Block` +output when the lowering succeeds. + +This is the structural lemma that lets the SimpleStorage native dispatcher +bridge be peeled past its outer block wrapper without unfolding `buildSwitch`. +-/ +private theorem lowerStmtsNative_single_block_ok_singleton + (stmts : List Yul.YulStmt) + (lowered : List EvmYul.Yul.Ast.Stmt) + (h : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Yul.YulStmt.block stmts] = .ok lowered) : + ∃ inner, lowered = [.Block inner] := by + exact Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNative_single_block_ok_singleton + stmts lowered h + +/-- The `simpleStorageNativeDispatcherStmts` lowering succeeds and equals the +SimpleStorage native witness dispatcher contents. + +The outer success is inherited from +`Compiler.SimpleStorageNativeWitness.lowerRuntimeContractNative_eq` (which +itself uses the existing `native_decide` trust chain on the runtime witness), +combined with the structural single-statement equation. -/ +private theorem simpleStorageNativeDispatcherStmts_lowering_ok : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch + simpleStorageIRContract.functions none none] = + .ok simpleStorageNativeDispatcherStmts := by + have hOuter := Compiler.SimpleStorageNativeWitness.lowerRuntimeContractNative_eq + rw [simpleStorage_runtimeCode_eq_single_dispatcher] at hOuter + rw [lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative] at hOuter + · cases hL : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch + simpleStorageIRContract.functions none none] with + | ok stmts => + simp [simpleStorageNativeDispatcherStmts, hL] + | error err => + rw [hL] at hOuter + simp at hOuter + · intro name params rets body h' + cases h' + +/-- The SimpleStorage native dispatcher statement list is a singleton `.Block`. + +Reason: `buildSwitch` produces a `Yul.YulStmt.block`, which the native lowering +maps to `[.Block inner]` for the lowered inner statements. Combined with the +fact that the lowering succeeds (above), this exposes the inner block shape +without further computation. -/ +private theorem simpleStorageNativeDispatcherStmts_exists_singleton_block : + ∃ inner : List EvmYul.Yul.Ast.Stmt, + simpleStorageNativeDispatcherStmts = [.Block inner] := by + have hOk := simpleStorageNativeDispatcherStmts_lowering_ok + -- buildSwitch produces a YulStmt.block by definition. + have hBlock : + Compiler.CodegenCommon.buildSwitch + simpleStorageIRContract.functions none none = + Yul.YulStmt.block _ := rfl + rw [hBlock] at hOk + exact lowerStmtsNative_single_block_ok_singleton _ _ hOk + +private noncomputable def simpleStorageNativeDispatcherInnerStmts : + List EvmYul.Yul.Ast.Stmt := + Classical.choose simpleStorageNativeDispatcherStmts_exists_singleton_block + +private theorem simpleStorageNativeDispatcherStmts_eq_singleton_block : + simpleStorageNativeDispatcherStmts = + [.Block simpleStorageNativeDispatcherInnerStmts] := + Classical.choose_spec simpleStorageNativeDispatcherStmts_exists_singleton_block + +/-- Transitive form of the SimpleStorage native dispatcher shape: combining +the lowered-stmts and singleton-block equalities exposes the dispatcher value +as `.Block [.Block ]`, which is the exact shape consumed by the harness +dispatcher-exec peel lemma. -/ +private theorem simpleStorageNativeContract_dispatcher_eq_singleton_block_inner : + Compiler.SimpleStorageNativeWitness.nativeContract.dispatcher = + .Block [.Block simpleStorageNativeDispatcherInnerStmts] := by + rw [simpleStorageNativeContract_dispatcher_eq_lowered_stmts, + simpleStorageNativeDispatcherStmts_eq_singleton_block] + +/-- Reify the SimpleStorage native witness contract as a record whose +dispatcher is the doubly-blocked inner statement list. + +This packages record-η with the lowered + singleton-block dispatcher +equalities so that the harness peel lemmas (which expect a +`{ dispatcher := .Block body, functions := … }` shape) apply in one rewrite. -/ +private theorem simpleStorageNativeContract_eq_record_inner_block : + Compiler.SimpleStorageNativeWitness.nativeContract = + { dispatcher := .Block [.Block simpleStorageNativeDispatcherInnerStmts] + functions := + Compiler.SimpleStorageNativeWitness.nativeContract.functions } := by + have hEta : Compiler.SimpleStorageNativeWitness.nativeContract = + (⟨Compiler.SimpleStorageNativeWitness.nativeContract.dispatcher, + Compiler.SimpleStorageNativeWitness.nativeContract.functions⟩ : + EvmYul.Yul.Ast.YulContract) := rfl + rw [hEta, simpleStorageNativeContract_dispatcher_eq_singleton_block_inner] + +/-- Dispatcher-exec for the SimpleStorage native witness peels TWO outer +`.Block` wrappers (the function-body wrapper installed by the dispatcher exec +plus the singleton-block emitted by `buildSwitch`'s native lowering) into a +direct `EvmYul.Yul.exec` over the inner statement list. + +This collapses the bridge's dispatcher invocation into the same shape the +harness's per-selector body lemmas already speak about, in preparation for +discharging the bridge from those lemmas. -/ +private theorem simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec + (peeledFuel : Nat) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ peeledFuel))) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = + EvmYul.Yul.exec (Nat.succ peeledFuel) + (.Block simpleStorageNativeDispatcherInnerStmts) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) := by + rw [simpleStorageNativeContract_eq_record_inner_block] + rw [Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ peeledFuel) [.Block simpleStorageNativeDispatcherInnerStmts] + Compiler.SimpleStorageNativeWitness.nativeContract.functions + tx storage observableSlots] + rw [Compiler.Proofs.YulGeneration.Backends.Native.exec_singleton_block_eq_exec_block] + +/-- A successful lowering of a singleton `[.block stmts]` reveals exactly the +inner statement-list lowering. This is the structural counterpart of +`lowerStmtsNative_single_block_ok_singleton`: instead of merely existing, the +`inner` argument is the *output* of the inner statement-list lowering. -/ +private theorem lowerStmtsNative_block_stmts_eq + (stmts : List Yul.YulStmt) + (inner : List EvmYul.Yul.Ast.Stmt) + (h : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNative + [Yul.YulStmt.block stmts] = .ok [.Block inner]) : + ∃ next : Nat, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + (Compiler.Proofs.YulGeneration.Backends.yulStmtsIdentifierNames + [Yul.YulStmt.block stmts]) + 0 stmts = .ok (inner, next) := by + exact Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNative_block_stmts_eq + stmts inner h + +/-- A `.let_`-headed statement-list lowering peels its head into a singleton +`.Let` statement and threads the unchanged switch counter through the tail. +This generic peel is the per-statement complement of +`lowerStmtsNative_block_stmts_eq`: combined, they reduce a successful native +lowering of a `.let_`-headed block to the lowering of its tail. -/ +private theorem lowerStmtsNativeWithSwitchIds_let_head_eq + (reservedNames : List String) (n0 : Nat) + (name : String) (value : Yul.YulExpr) + (rest : List Yul.YulStmt) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + (Yul.YulStmt.let_ name value :: rest) = .ok (inner, next)) : + ∃ rest' : List EvmYul.Yul.Ast.Stmt, + inner = EvmYul.Yul.Ast.Stmt.Let [name] + (some + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative value)) + :: rest' ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 rest = .ok (rest', next) := by + exact Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_let_head_eq + reservedNames n0 name value + rest inner next h + +/-- An `.if_`-headed statement-list lowering peels its head into a singleton +`.If` statement and threads the body's switch-counter advance through to the +tail. This is the per-statement complement of +`lowerStmtsNativeWithSwitchIds_let_head_eq` for the `if_` case: combined with +`lowerStmtsNative_block_stmts_eq`, it lets a successful native lowering of a +block be peeled past an `.if_`-headed source statement. -/ +private theorem lowerStmtsNativeWithSwitchIds_if_head_eq + (reservedNames : List String) (n0 : Nat) + (cond : Yul.YulExpr) (body : List Yul.YulStmt) + (rest : List Yul.YulStmt) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 + (Yul.YulStmt.if_ cond body :: rest) = .ok (inner, next)) : + ∃ (body' : List EvmYul.Yul.Ast.Stmt) (midN : Nat) + (rest' : List EvmYul.Yul.Ast.Stmt), + inner = EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative cond) + body' :: rest' ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n0 body = .ok (body', midN) ∧ + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames midN rest = .ok (rest', next) := by + exact Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_if_head_eq + reservedNames n0 cond body rest + inner next h + +set_option linter.unusedSimpArgs false in +/-- A singleton `.switch`-headed statement-list lowering reduces to a singleton +`.lowerNativeSwitchBlock` over the same source expression. This is the +companion of `lowerStmtsNativeWithSwitchIds_let_head_eq` and `_if_head_eq` +specialized to a single source-level `switch` statement (no tail), which is +exactly the shape produced by the body of `buildSwitch`'s selector-hit `if`. +The case-bodies and default-body lowerings remain abstract because their +shape depends on the concrete contract `funcs` list. -/ +private theorem lowerStmtsNativeWithSwitchIds_singleton_switch_eq + (reservedNames : List String) (n0 : Nat) + (expr : Yul.YulExpr) (cases : List (Nat × List Yul.YulStmt)) + (defaultCase : Option (List Yul.YulStmt)) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Yul.YulStmt.switch expr cases defaultCase] = .ok (inner, next)) : + ∃ (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (default' : List EvmYul.Yul.Ast.Stmt), + inner = [Backends.lowerNativeSwitchBlock expr + (Backends.freshNativeSwitchId reservedNames n0) cases' default'] := by + exact Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_singleton_switch_eq + reservedNames n0 expr + cases defaultCase inner next h + +/-- The head of the SimpleStorage native dispatcher inner-block is the lowered +`let __has_selector := ...` statement. This peels one further layer beyond the +singleton-block extraction (`simpleStorageNativeDispatcherStmts_eq_singleton_block`) +by applying the cons/`_let` lowering equations to the head of `buildSwitch`'s +3-statement block. The remaining tail is left abstract — downstream peels will +expose the second and third statements. -/ +private theorem simpleStorageNativeDispatcherInnerStmts_head_let_exists : + ∃ (e : EvmYul.Yul.Ast.Expr) (rest : List EvmYul.Yul.Ast.Stmt), + simpleStorageNativeDispatcherInnerStmts = + EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] (some e) :: rest := by + have hOk := simpleStorageNativeDispatcherStmts_lowering_ok + rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk + obtain ⟨next, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk + -- `buildSwitch ssIRC.functions none none` unfolds (definitionally) to a + -- 3-statement `YulStmt.block` whose head is `let __has_selector := …`, so + -- `hInner` is already a `let_`-headed lowering at the source spine. + obtain ⟨rest', hSplit, _⟩ := + lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner + exact ⟨_, rest', hSplit⟩ + +/-- The first two statements of the SimpleStorage native dispatcher inner-block +are exactly the lowered `let __has_selector := ...` and the lowered selector-miss +guard `if iszero(__has_selector) { revert(0,0) }`. This peels the second +statement of `buildSwitch`'s 3-statement source block by chaining +`lowerStmtsNative_block_stmts_eq`, `lowerStmtsNativeWithSwitchIds_let_head_eq`, +and `lowerStmtsNativeWithSwitchIds_if_head_eq`. -/ +private theorem simpleStorageNativeDispatcherInnerStmts_let_if_head_exists : + ∃ (e : EvmYul.Yul.Ast.Expr) (c : EvmYul.Yul.Ast.Expr) + (body : List EvmYul.Yul.Ast.Stmt) (rest : List EvmYul.Yul.Ast.Stmt), + simpleStorageNativeDispatcherInnerStmts = + EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] (some e) :: + EvmYul.Yul.Ast.Stmt.If c body :: + rest := by + have hOk := simpleStorageNativeDispatcherStmts_lowering_ok + rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk + obtain ⟨next, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk + obtain ⟨rest', hLet, hRestLowering⟩ := + lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner + obtain ⟨body', _midN, rest'', hIf, _, _⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering + rw [hIf] at hLet + exact ⟨_, _, body', rest'', hLet⟩ + +/-- The full inner-block of the SimpleStorage native dispatcher has exactly the +expected three-statement shape: the lowered `let __has_selector := …`, the +selector-miss `if iszero(__has_selector) { … }` guard, and the selector-hit +`if __has_selector { switch … }` body. The trailing list is empty because +`buildSwitch` produces a 3-statement source block. -/ +private theorem simpleStorageNativeDispatcherInnerStmts_eq_let_if_if : + ∃ (e : EvmYul.Yul.Ast.Expr) (c1 : EvmYul.Yul.Ast.Expr) + (body1 : List EvmYul.Yul.Ast.Stmt) + (c2 : EvmYul.Yul.Ast.Expr) (body2 : List EvmYul.Yul.Ast.Stmt), + simpleStorageNativeDispatcherInnerStmts = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] (some e), + EvmYul.Yul.Ast.Stmt.If c1 body1, + EvmYul.Yul.Ast.Stmt.If c2 body2] := by + have hOk := simpleStorageNativeDispatcherStmts_lowering_ok + rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk + obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk + obtain ⟨rest', hLet, hRestLowering⟩ := + lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner + obtain ⟨body1', _, rest'', hIf1, _, hRest1⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering + obtain ⟨body2', _, rest''', hIf2, _, hRest2⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 + rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Except.ok.injEq, Prod.mk.injEq] at hRest2 + obtain ⟨hNil, _⟩ := hRest2 + subst hNil + rw [hIf2] at hIf1 + rw [hIf1] at hLet + exact ⟨_, _, body1', _, body2', hLet⟩ + +/-- The lowered RHS expression of the SimpleStorage native dispatcher's +`__has_selector` let. Pinned via `Classical.choose` from the let/if/if shape +existential so it can be referenced by downstream proofs without re-`obtain`-ing +the witness each time. -/ +private noncomputable def simpleStorageNativeDispatcher_letValue : + EvmYul.Yul.Ast.Expr := + Classical.choose simpleStorageNativeDispatcherInnerStmts_eq_let_if_if + +/-- The lowered condition of the SimpleStorage native dispatcher's +selector-miss `if iszero(__has_selector) { … }` guard. -/ +private noncomputable def simpleStorageNativeDispatcher_if1Cond : + EvmYul.Yul.Ast.Expr := + Classical.choose + (Classical.choose_spec simpleStorageNativeDispatcherInnerStmts_eq_let_if_if) + +/-- The lowered body of the SimpleStorage native dispatcher's selector-miss +guard (the `revert(0,0)` revert path). -/ +private noncomputable def simpleStorageNativeDispatcher_if1Body : + List EvmYul.Yul.Ast.Stmt := + Classical.choose + (Classical.choose_spec + (Classical.choose_spec simpleStorageNativeDispatcherInnerStmts_eq_let_if_if)) + +/-- The lowered condition of the SimpleStorage native dispatcher's +selector-hit `if __has_selector { switch … }` body. -/ +private noncomputable def simpleStorageNativeDispatcher_if2Cond : + EvmYul.Yul.Ast.Expr := + Classical.choose + (Classical.choose_spec + (Classical.choose_spec + (Classical.choose_spec + simpleStorageNativeDispatcherInnerStmts_eq_let_if_if))) + +/-- The lowered body of the SimpleStorage native dispatcher's selector-hit +`if __has_selector { switch … }` body — i.e., the singleton list containing +the lowered `switch` over the three generated cases. -/ +private noncomputable def simpleStorageNativeDispatcher_if2Body : + List EvmYul.Yul.Ast.Stmt := + Classical.choose + (Classical.choose_spec + (Classical.choose_spec + (Classical.choose_spec + (Classical.choose_spec + simpleStorageNativeDispatcherInnerStmts_eq_let_if_if)))) + +/-- Closed-form decomposition of the SimpleStorage native dispatcher inner +statement list using the named witness defs. Eliminates the existential +boilerplate from the `_eq_let_if_if` lemma so future selector-case proofs can +rewrite the dispatcher inner-stmts to a literal 3-element list. -/ +private theorem simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if : + simpleStorageNativeDispatcherInnerStmts = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some simpleStorageNativeDispatcher_letValue), + EvmYul.Yul.Ast.Stmt.If + simpleStorageNativeDispatcher_if1Cond + simpleStorageNativeDispatcher_if1Body, + EvmYul.Yul.Ast.Stmt.If + simpleStorageNativeDispatcher_if2Cond + simpleStorageNativeDispatcher_if2Body] := + Classical.choose_spec + (Classical.choose_spec + (Classical.choose_spec + (Classical.choose_spec + (Classical.choose_spec + simpleStorageNativeDispatcherInnerStmts_eq_let_if_if)))) + +/-- Composed structural form of the SimpleStorage native dispatcher exec: +the doubly-blocked dispatcher is exposed at the concrete inner three-statement +spine using the pinned named witnesses. This combines +`simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec` with +`simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if`, replacing the +existential let/if/if shape with a concrete equation in named witnesses. -/ +private theorem simpleStorageNativeContract_dispatcherExec_eq_named_let_if_if_block_exec + (peeledFuel : Nat) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ peeledFuel))) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = + EvmYul.Yul.exec (Nat.succ peeledFuel) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some simpleStorageNativeDispatcher_letValue), + EvmYul.Yul.Ast.Stmt.If + simpleStorageNativeDispatcher_if1Cond + simpleStorageNativeDispatcher_if1Body, + EvmYul.Yul.Ast.Stmt.If + simpleStorageNativeDispatcher_if2Cond + simpleStorageNativeDispatcher_if2Body]) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) := by + rw [simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec, + simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if] + +/-- Concrete head exposure of the SimpleStorage native dispatcher inner-block: +its first statement is the lowered `let __has_selector := iszero(lt(calldatasize(), 4))` +that `buildSwitch` emits, with the source-Yul RHS pinned explicitly. This is +the same peel as `simpleStorageNativeDispatcherInnerStmts_head_let_exists` but +exposes the *concrete* lowered RHS (not just an abstract Lean witness), so the +`Classical.choose`-pinned `simpleStorageNativeDispatcher_letValue` can be +equated to it via head injection. -/ +private theorem simpleStorageNativeDispatcherInnerStmts_concrete_let_head : + ∃ rest : List EvmYul.Yul.Ast.Stmt, + simpleStorageNativeDispatcherInnerStmts = + EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "iszero" + [Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit 4]]))) :: rest := by + have hOk := simpleStorageNativeDispatcherStmts_lowering_ok + rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk + obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk + obtain ⟨rest', hSplit, _⟩ := + lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner + exact ⟨rest', hSplit⟩ + +/-- Concrete-form equation for the SimpleStorage native dispatcher's full inner +3-statement block, pinning *all three* source-Yul expressions (the let RHS, the +selector-miss `iszero(__has_selector)` guard, and the selector-hit +`__has_selector` guard) to the literal Yul expressions emitted by +`buildSwitch`. Only the two `If` bodies remain existential, since they depend +on the lowering of the inner switch over the generated cases. This is the +companion of `simpleStorageNativeDispatcherInnerStmts_eq_let_if_if` with +abstract Yul witnesses replaced by concrete syntax. -/ +private theorem simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_if : + ∃ (body1 body2 : List EvmYul.Yul.Ast.Stmt), + simpleStorageNativeDispatcherInnerStmts = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "iszero" + [Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "iszero" + [Yul.YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.ident "__has_selector")) + body2] := by + have hOk := simpleStorageNativeDispatcherStmts_lowering_ok + rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk + obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk + obtain ⟨rest', hLet, hRestLowering⟩ := + lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner + obtain ⟨body1', _, rest'', hIf1, _, hRest1⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering + obtain ⟨body2', _, rest''', hIf2, _, hRest2⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 + rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Except.ok.injEq, Prod.mk.injEq] at hRest2 + obtain ⟨hNil, _⟩ := hRest2 + subst hNil + rw [hIf2] at hIf1 + rw [hIf1] at hLet + exact ⟨body1', body2', hLet⟩ + +/-- Strengthened concrete-form equation for the SimpleStorage native dispatcher +inner-block: same as `simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_if` +except the body of the second (selector-hit) `If` is pinned to a singleton +`lowerNativeSwitchBlock` over the source-Yul `selectorExpr` scrutinee. The +selector cases and default body remain existential because they depend on the +contract's `functions` list. This is the next dispatcher peel beyond the +let/if/if shape and is the foundation for replacing the Classical.choose-pinned +`simpleStorageNativeDispatcher_if2Body` with a concrete switch block. -/ +private theorem simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton : + ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (default' : List EvmYul.Yul.Ast.Stmt), + simpleStorageNativeDispatcherInnerStmts = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some (Backends.lowerExprNative + (Yul.YulExpr.call "iszero" + [Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "iszero" [Yul.YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' default']] := by + have hOk := simpleStorageNativeDispatcherStmts_lowering_ok + rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk + obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk + obtain ⟨_, hLet, hRestLowering⟩ := + lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner + obtain ⟨body1', _, _, hIf1, _, hRest1⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering + obtain ⟨_, _, _, hIf2, hBody2, hRest2⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 + rw [Backends.lowerStmtsNativeWithSwitchIds_nil, + Except.ok.injEq, Prod.mk.injEq] at hRest2 + obtain ⟨hNil, _⟩ := hRest2 + subst hNil + obtain ⟨cases', default', hBody2Eq⟩ := + lowerStmtsNativeWithSwitchIds_singleton_switch_eq _ _ _ _ _ _ _ hBody2 + rw [hBody2Eq] at hIf2; rw [hIf2] at hIf1; rw [hIf1] at hLet + exact ⟨body1', _, cases', default', hLet⟩ + +/-- WithSwitchIds-form companion of `lowerStmtsNative_revert_zero_zero`: at any +`reservedNames`/`nextSwitchId` pair, the singleton list `[expr (revert(0,0))]` +emitted by `defaultDispatchCase none none` lowers to +`[nativeRevertZeroZeroStmt]` while leaving the switch counter unchanged. The +dispatcher peel uses `lowerStmtsNativeWithSwitchIds` directly (via +`_block_stmts_eq` / `_let_head_eq` / `_if_head_eq`), so the wrapper-level +`lowerStmtsNative_revert_zero_zero` lemma alone is insufficient when pinning +the selector-miss `If` body. -/ +private theorem lowerStmtsNativeWithSwitchIds_revert_zero_zero + (reservedNames : List String) (n : Nat) : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames n + [Yul.YulStmt.expr (Yul.YulExpr.call "revert" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 0])] = + .ok ([Backends.Native.nativeRevertZeroZeroStmt], n) := by + exact Backends.Native.lowerStmtsNativeWithSwitchIds_revert_zero_zero + reservedNames n + +set_option linter.unusedSimpArgs false in +/-- Strengthened companion of `lowerStmtsNativeWithSwitchIds_singleton_switch_eq`: +when the source-level switch's `defaultCase` is fixed to the +`defaultDispatchCase none none` body — namely the singleton list +`[expr (revert(0,0))]` — the lowered default body is concretely +`[nativeRevertZeroZeroStmt]`. The lowered case bodies remain existential +(they depend on the contract `funcs` list). This pins the previously-existential +`default'` produced by `_singleton_switch_eq`, unblocking downstream proofs +that need to plug the lowered-switch exec into a concrete default-revert +endpoint. -/ +private theorem lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq + (reservedNames : List String) (n0 : Nat) + (expr : Yul.YulExpr) (cases : List (Nat × List Yul.YulStmt)) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Yul.YulStmt.switch expr cases + (some [Yul.YulStmt.expr (Yul.YulExpr.call "revert" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 0])])] = .ok (inner, next)) : + ∃ (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), + inner = [Backends.lowerNativeSwitchBlock expr + (Backends.freshNativeSwitchId reservedNames n0) cases' + [Backends.Native.nativeRevertZeroZeroStmt]] := by + exact Backends.Native.lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq + reservedNames n0 expr cases inner next h + +set_option linter.unusedSimpArgs false in +/-- Source-lowered companion of `_singleton_switch_revert_default_eq`: also +exposes the `lowerSwitchCasesNativeWithSwitchIds` equation linking the source +case list to the lowered `cases'`. Downstream selector-miss reductions chain +this with `lowerSwitchCasesNativeWithSwitchIds_tags_eq` / +`lowerSwitchCasesNativeWithSwitchIds_find?_none` to lift source-level selector +facts through the lowering. -/ +private theorem lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered + (reservedNames : List String) (n0 : Nat) + (expr : Yul.YulExpr) (cases : List (Nat × List Yul.YulStmt)) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Yul.YulStmt.switch expr cases + (some [Yul.YulStmt.expr (Yul.YulExpr.call "revert" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 0])])] = .ok (inner, next)) : + ∃ (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + inner = [Backends.lowerNativeSwitchBlock expr + (Backends.freshNativeSwitchId reservedNames n0) cases' + [Backends.Native.nativeRevertZeroZeroStmt]] ∧ + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) cases = + .ok (cases', midN) := by + exact Backends.Native.lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered + reservedNames n0 expr cases inner next h + +/-- Strengthened companion of `simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton`: +the lowered default body of the inner switch is pinned to the concrete +`[nativeRevertZeroZeroStmt]` singleton. The lowered case bodies (and the +selector-miss `If` body `body1`) remain existential as before. Combines the +existing concrete decomposition with the new +`lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq`, exploiting +the definitional fact that `simpleStorageIRContract` has both `fallback` and +`receive` set to `none`, so the switch's source-level `defaultCase` is +`defaultDispatchCase none none = [revert(0,0)]`. -/ +private theorem simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default : + ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), + simpleStorageNativeDispatcherInnerStmts = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some (Backends.lowerExprNative + (Yul.YulExpr.call "iszero" + [Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "iszero" [Yul.YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' + [Backends.Native.nativeRevertZeroZeroStmt]]] := by + have hOk := simpleStorageNativeDispatcherStmts_lowering_ok + rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk + obtain ⟨body1, reservedNames, n0, cases', _, hInner, _⟩ := + Backends.Native.buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered + simpleStorageIRContract.functions simpleStorageNativeDispatcherInnerStmts hOk + exact ⟨body1, Backends.freshNativeSwitchId reservedNames n0, cases', hInner⟩ + +/-- The source-level switch cases that `buildSwitch` emits for SimpleStorage +(one entry per source IR function, keyed by selector). Used by the +`_sourceLowered` companion below as the explicit input to +`lowerSwitchCasesNativeWithSwitchIds`, anchoring the switch lowering to the +concrete source-level selector list. -/ +private abbrev simpleStorageBuildSwitchSourceCases : List (Nat × List Yul.YulStmt) := + simpleStorageIRContract.functions.map (fun fn => + (fn.selector, + Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" + ([Compiler.CodegenCommon.calldatasizeGuard fn.params.length] ++ fn.body))) + +/-- Source-lowered companion of `_eq_concrete_let_if_switchSingleton_revert_default`: +additionally exposes the lowering equation for the buildSwitch-emitted source +case list `simpleStorageBuildSwitchSourceCases` into the lowered `cases'`. +Bridge lemma for the selector-miss closed-form: chained with +`lowerSwitchCasesNativeWithSwitchIds_tags_eq` it converts source-level +selector facts into lowered-level `find?` results. -/ +private theorem simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default_sourceLowered : + ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + simpleStorageNativeDispatcherInnerStmts = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some (Backends.lowerExprNative (Yul.YulExpr.call "iszero" + [Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "iszero" [Yul.YulExpr.ident "__has_selector"])) body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [Backends.Native.nativeRevertZeroZeroStmt]]] ∧ + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + simpleStorageBuildSwitchSourceCases = .ok (cases', midN) := by + have hOk := simpleStorageNativeDispatcherStmts_lowering_ok + rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk + simpa [simpleStorageBuildSwitchSourceCases] using + (Backends.Native.buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered + simpleStorageIRContract.functions simpleStorageNativeDispatcherInnerStmts hOk) + +/-- The `Classical.choose`-pinned let RHS of the SimpleStorage native dispatcher +equals the lowered `iszero(lt(calldatasize(), 4))` Yul expression that +`buildSwitch` emits. Combining the named-form decomposition +(`simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if`) with the +concrete-head exposure +(`simpleStorageNativeDispatcherInnerStmts_concrete_let_head`) and head +injection eliminates the structural existential between the named witness and +the concrete source expression, letting downstream proofs evaluate the let +RHS directly via the existing harness lemmas. -/ +private theorem simpleStorageNativeDispatcher_letValue_eq : + simpleStorageNativeDispatcher_letValue = + Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "iszero" + [Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit 4]]) := by + obtain ⟨_, hConcrete⟩ := + simpleStorageNativeDispatcherInnerStmts_concrete_let_head + have hCombo := + simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete + simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.Let.injEq, Option.some.injEq, + true_and] at hCombo + exact hCombo.1 + +/-- The `Classical.choose`-pinned selector-miss guard condition of the +SimpleStorage native dispatcher equals the lowered `iszero(__has_selector)` +Yul expression that `buildSwitch` emits. Derived by head injection from the +concrete-form full equation and the named-form decomposition. -/ +private theorem simpleStorageNativeDispatcher_if1Cond_eq : + simpleStorageNativeDispatcher_if1Cond = + Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.call "iszero" + [Yul.YulExpr.ident "__has_selector"]) := by + obtain ⟨_, _, hConcrete⟩ := + simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_if + have hCombo := + simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete + simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo + exact hCombo.2.1.1 + +/-- The `Classical.choose`-pinned selector-hit guard condition of the +SimpleStorage native dispatcher equals the lowered `__has_selector` ident +expression that `buildSwitch` emits. Derived by head injection from the +concrete-form full equation and the named-form decomposition. -/ +private theorem simpleStorageNativeDispatcher_if2Cond_eq : + simpleStorageNativeDispatcher_if2Cond = + Compiler.Proofs.YulGeneration.Backends.lowerExprNative + (Yul.YulExpr.ident "__has_selector") := by + obtain ⟨_, _, hConcrete⟩ := + simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_if + have hCombo := + simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete + simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo + exact hCombo.2.2.1.1 + +/-- The `Classical.choose`-pinned selector-hit `If` body of the SimpleStorage +native dispatcher equals a singleton `lowerNativeSwitchBlock` over the +source-Yul `selectorExpr` (i.e., `shr(selectorShift, calldataload(0))`). The +switch-id, lowered case bodies, and lowered default body remain existential +because they depend on the concrete contract `functions` list — but their +existence as a closed-form switch block is enough to drive the next dispatcher +peel into selector-case dispatch. Derived by head injection from the +strengthened concrete-form `_eq_concrete_let_if_switchSingleton` and the +named-form decomposition. -/ +private theorem simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_exists : + ∃ (switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (default' : List EvmYul.Yul.Ast.Stmt), + simpleStorageNativeDispatcher_if2Body = + [Compiler.Proofs.YulGeneration.Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' default'] := by + obtain ⟨_, switchId, cases', default', hConcrete⟩ := + simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton + have hCombo := + simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete + simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo + exact ⟨switchId, cases', default', hCombo.2.2.1.2⟩ + +/-- Strengthened companion of `simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_exists`: +the lowered default body of the dispatcher's selector-hit switch is pinned to +`[nativeRevertZeroZeroStmt]`. Derived by head injection from the strengthened +concrete-form `_eq_concrete_let_if_switchSingleton_revert_default` and the +named-form decomposition. -/ +private theorem simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_exists : + ∃ (switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), + simpleStorageNativeDispatcher_if2Body = + [Compiler.Proofs.YulGeneration.Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' + [Backends.Native.nativeRevertZeroZeroStmt]] := by + obtain ⟨_, switchId, cases', hConcrete⟩ := + simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default + have hCombo := + simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete + simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo + exact ⟨switchId, cases', hCombo.2.2.1.2⟩ + +/-- Source-lowered companion of `_if2Body_eq_lowerSwitchBlock_revert_default_exists`: +the `if2Body` equality additionally exposes `switchId = +freshNativeSwitchId reservedNames n0` and the source-cases lowering equation +linking `simpleStorageBuildSwitchSourceCases` to the lowered `cases'`. This is +the form the dispatcher selector-miss closed-form consumes — chaining it with +`lowerSwitchCasesNativeWithSwitchIds_tags_eq` lifts source-level selector +facts through the lowering. -/ +private theorem simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_sourceLowered : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + simpleStorageNativeDispatcher_if2Body = + [Compiler.Proofs.YulGeneration.Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [Backends.Native.nativeRevertZeroZeroStmt]] ∧ + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + simpleStorageBuildSwitchSourceCases = .ok (cases', midN) := by + obtain ⟨_, reservedNames, n0, cases', midN, hConcrete, hLowerCases⟩ := + simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default_sourceLowered + have hCombo := + simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hConcrete + simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo + exact ⟨reservedNames, n0, cases', midN, hCombo.2.2.1.2, hLowerCases⟩ + +/-- The `Classical.choose`-pinned selector-miss `If` body of the SimpleStorage +native dispatcher equals the singleton list `[nativeRevertZeroZeroStmt]`. +Combines `simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if` with a +fully-pinned concrete-form decomposition of the inner block (where body1 is +also pinned via the WithSwitchIds revert lowering equation), then uses head +injection on the second `If` to extract the body equation. Lets downstream +selector-miss exec proofs invoke `exec_revert_zero_zero_error` directly. -/ +private theorem simpleStorageNativeDispatcher_if1Body_eq : + simpleStorageNativeDispatcher_if1Body = + [Backends.Native.nativeRevertZeroZeroStmt] := by + have hOk := simpleStorageNativeDispatcherStmts_lowering_ok + rw [simpleStorageNativeDispatcherStmts_eq_singleton_block] at hOk + obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ hOk + obtain ⟨rest', hLet, hRestLowering⟩ := + lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner + obtain ⟨body1', _, rest'', hIf1, hBody1, hRest1⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering + obtain ⟨body2', _, rest''', hIf2, _, hRest2⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 + rw [Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Except.ok.injEq, Prod.mk.injEq] at hRest2 + obtain ⟨hNil, _⟩ := hRest2 + subst hNil + have hDef : + Compiler.CodegenCommon.defaultDispatchCase + (none : Option Compiler.IREntrypoint) + (none : Option Compiler.IREntrypoint) = + [Yul.YulStmt.expr + (Yul.YulExpr.call "revert" [Yul.YulExpr.lit 0, Yul.YulExpr.lit 0])] := + rfl + rw [hDef, lowerStmtsNativeWithSwitchIds_revert_zero_zero, + Except.ok.injEq, Prod.mk.injEq] at hBody1 + obtain ⟨hBody1Eq, _⟩ := hBody1 + subst hBody1Eq + rw [hIf2] at hIf1 + rw [hIf1] at hLet + have hCombo := + simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if.symm.trans hLet + simp only [List.cons.injEq, EvmYul.Yul.Ast.Stmt.If.injEq] at hCombo + exact hCombo.2.1.2 + +/-- Closed-form selector-miss revert exec for the SimpleStorage native +dispatcher's first `If` body. The body is the singleton list +`[nativeRevertZeroZeroStmt]` (by `simpleStorageNativeDispatcher_if1Body_eq`), +so a `.Block` execution at any fuel `≥ 7` peels the head via +`exec_block_cons_error` and reduces to `exec_revert_zero_zero_error`, +producing EVMYulLean's `Revert` exception. Self-contained — no premise on +state/eval is needed because the body has no side effects before the revert. + +This is the per-statement halt lemma the selector-miss dispatcher proof will +chain after the `let __has_selector := …` and `if iszero(__has_selector)` +peels: once `__has_selector = 0` is established, the if guard fires, and this +lemma immediately closes the dispatcher result as `.error Revert`. -/ +private theorem exec_block_simpleStorageNativeDispatcher_if1Body_revert + (fuel : Nat) (state : EvmYul.Yul.State) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) : + EvmYul.Yul.exec (fuel + 7) (.Block simpleStorageNativeDispatcher_if1Body) + codeOverride state = + .error EvmYul.Yul.Exception.Revert := by + rw [simpleStorageNativeDispatcher_if1Body_eq] + exact Compiler.Proofs.YulGeneration.Backends.Native.exec_block_cons_error + (fuel + 6) + Compiler.Proofs.YulGeneration.Backends.Native.nativeRevertZeroZeroStmt + [] codeOverride state EvmYul.Yul.Exception.Revert + (Compiler.Proofs.YulGeneration.Backends.Native.exec_revert_zero_zero_error + fuel state codeOverride) + +/-- Composed dispatcher peel exposing the SimpleStorage native dispatcher's +inner three-statement block exec as a singleton `lowerNativeSwitchBlock` exec +on the post-Let state. Chains the named let/if/if normalization with the +let-selector / if1-skip / if2-take peel +(`exec_block_letSelector_if1Skip_if2Take_initialState_fuel`, which discharges +calldatasize ≥ 4 via `hNoWrap` so the let binds `__has_selector` to 1) and the +just-landed `simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_exists` +characterization, leaving the dispatcher inner-block exec equal to a single +lowered switch-block exec on +`(nativeSwitchInitialOkState).insert "__has_selector" 1`. The switch-id, +lowered case bodies, and lowered default body remain existential — they are +fixed by the concrete `simpleStorageIRContract.functions` list and threaded +through later case-dispatch peels using +`exec_lowerNativeSwitchBlock_simpleStorageConcrete_*` lemmas. -/ +private theorem exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_exec + (fuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (default' : List EvmYul.Yul.Ast.Stmt), + EvmYul.Yul.exec (fuel + 12) + (.Block simpleStorageNativeDispatcherInnerStmts) + (some contract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + 8) + (.Block + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' default']) + (some contract) + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + contract tx storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + obtain ⟨switchId, cases', default', hIf2Body⟩ := + simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_exists + refine ⟨switchId, cases', default', ?_⟩ + rw [simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if, + simpleStorageNativeDispatcher_letValue_eq, + simpleStorageNativeDispatcher_if1Cond_eq, + simpleStorageNativeDispatcher_if2Cond_eq, hIf2Body] + exact Backends.Native.exec_block_letSelector_if1Skip_if2Take_initialState_fuel + fuel contract tx storage observableSlots "__has_selector" + simpleStorageNativeDispatcher_if1Body + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' default'] + hNoWrap + +/-- Strengthened companion of `exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_exec` +where the lowered default body of the inner switch is pinned to +`[nativeRevertZeroZeroStmt]`. Uses +`simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_exists` +in place of the unpinned existential variant. -/ +private theorem exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec + (fuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), + EvmYul.Yul.exec (fuel + 12) + (.Block simpleStorageNativeDispatcherInnerStmts) + (some contract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + 8) + (.Block + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' + [Backends.Native.nativeRevertZeroZeroStmt]]) + (some contract) + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + contract tx storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + obtain ⟨switchId, cases', hIf2Body⟩ := + simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_exists + refine ⟨switchId, cases', ?_⟩ + rw [simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if, + simpleStorageNativeDispatcher_letValue_eq, + simpleStorageNativeDispatcher_if1Cond_eq, + simpleStorageNativeDispatcher_if2Cond_eq, hIf2Body] + exact Backends.Native.exec_block_letSelector_if1Skip_if2Take_initialState_fuel + fuel contract tx storage observableSlots "__has_selector" + simpleStorageNativeDispatcher_if1Body + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' + [Backends.Native.nativeRevertZeroZeroStmt]] + hNoWrap + +/-- Source-lowered companion of `exec_block_..._eq_lowerNativeSwitchBlock_revert_default_exec`: +the inner-stmts-to-lowered-switch-block exec equation additionally exposes +`switchId = freshNativeSwitchId reservedNames n0` and the source-cases lowering +equation linking `simpleStorageBuildSwitchSourceCases` to the lowered `cases'`. +Built by switching the underlying `if2Body` decomposition to its sourceLowered +companion. -/ +private theorem exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered + (fuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + EvmYul.Yul.exec (fuel + 12) + (.Block simpleStorageNativeDispatcherInnerStmts) + (some contract) + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + 8) + (.Block + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [Backends.Native.nativeRevertZeroZeroStmt]]) + (some contract) + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + contract tx storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) ∧ + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + simpleStorageBuildSwitchSourceCases = .ok (cases', midN) := by + obtain ⟨reservedNames, n0, cases', midN, hIf2Body, hLowerCases⟩ := + simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_sourceLowered + refine ⟨reservedNames, n0, cases', midN, ?_, hLowerCases⟩ + rw [simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if, + simpleStorageNativeDispatcher_letValue_eq, + simpleStorageNativeDispatcher_if1Cond_eq, + simpleStorageNativeDispatcher_if2Cond_eq, hIf2Body] + exact Backends.Native.exec_block_letSelector_if1Skip_if2Take_initialState_fuel + fuel contract tx storage observableSlots "__has_selector" + simpleStorageNativeDispatcher_if1Body + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [Backends.Native.nativeRevertZeroZeroStmt]] + hNoWrap + +/-- Bridge-level lift of the inner-block-to-lowerNativeSwitchBlock combinator: +chains `simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec` with the +just-landed `_innerStmts_eq_lowerNativeSwitchBlock_exec`, so the bridge's +`contractDispatcherExecResult` at fuel `peeledFuel + 14` reduces to an exec of +a singleton lowered-switch block at fuel `peeledFuel + 8` on +`(initialOk).insert "__has_selector" 1`. -/ +private theorem simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_exec + (peeledFuel : Nat) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (default' : List EvmYul.Yul.Ast.Stmt), + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (peeledFuel + 14) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = + EvmYul.Yul.exec (peeledFuel + 8) + (.Block + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' default']) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + obtain ⟨switchId, cases', default', hExec⟩ := + exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_exec + peeledFuel Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots hNoWrap + refine ⟨switchId, cases', default', ?_⟩ + have hShape : peeledFuel + 14 = + Nat.succ (Nat.succ (Nat.succ (peeledFuel + 11))) := by omega + rw [hShape, simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec + (peeledFuel + 11) tx storage observableSlots] + exact hExec + +/-- Strengthened companion of `simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_exec` +with the lowered default body pinned to `[nativeRevertZeroZeroStmt]`. Chains +the `_innerBlock_exec` combinator with the strengthened +`_innerStmts_eq_lowerNativeSwitchBlock_revert_default_exec`. This is the entry +point that downstream selector-miss bridge proofs will plug into the new +store-parametric `exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_fuel` +endpoint. -/ +private theorem simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec + (peeledFuel : Nat) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (peeledFuel + 14) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = + EvmYul.Yul.exec (peeledFuel + 8) + (.Block + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' + [Backends.Native.nativeRevertZeroZeroStmt]]) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + obtain ⟨switchId, cases', hExec⟩ := + exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec + peeledFuel Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots hNoWrap + refine ⟨switchId, cases', ?_⟩ + have hShape : peeledFuel + 14 = + Nat.succ (Nat.succ (Nat.succ (peeledFuel + 11))) := by omega + rw [hShape, simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec + (peeledFuel + 11) tx storage observableSlots] + exact hExec + +/-- Source-lowered companion of `_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec`: +the dispatcher-level reduction additionally exposes +`switchId = freshNativeSwitchId reservedNames n0` and the source-cases lowering +equation. This is the form selector-miss closed-form proofs will consume — +they open the existential, then chain `lowerSwitchCasesNativeWithSwitchIds_tags_eq` +to lift source-level selector facts (decided from `simpleStorageIRContract`) +into the lowered `cases'.find?` results required by the `_via_reduction` +endpoint. -/ +private theorem simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered + (peeledFuel : Nat) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (peeledFuel + 14) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = + EvmYul.Yul.exec (peeledFuel + 8) + (.Block + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [Backends.Native.nativeRevertZeroZeroStmt]]) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) ∧ + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + simpleStorageBuildSwitchSourceCases = .ok (cases', midN) := by + obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := + exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered + peeledFuel Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots hNoWrap + refine ⟨reservedNames, n0, cases', midN, ?_, hLowerCases⟩ + have hShape : peeledFuel + 14 = + Nat.succ (Nat.succ (Nat.succ (peeledFuel + 11))) := by omega + rw [hShape, simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec + (peeledFuel + 11) tx storage observableSlots] + exact hExec + +/-- Bridge-level selector-miss endpoint, parametric in `cases'` and `switchId`: +composes the harness-level +`exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error` with +the strengthened-reduction equation at the matching fuel +`peeledFuel = fuel + cases'.length + 5`. The reduction equation is taken as a +hypothesis so the caller can pin a specific `cases'` (e.g. by opening the +existential of `_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec`) +without forcing the fuel parameter to depend on a not-yet-bound term. This is +the direct selector-miss discharge composing into +`contractDispatcherExecResult = .error Revert`. -/ +private theorem simpleStorageNativeContract_dispatcherExec_selectorMiss_revert_via_reduction + (fuel selector switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFind : cases'.find? (fun entry => entry.1 == selector) = none) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size) + (hReduction : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + cases'.length + 19) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" + [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' + [Backends.Native.nativeRevertZeroZeroStmt]]) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1))) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + cases'.length + 19) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = + .error EvmYul.Yul.Exception.Revert := by + rw [hReduction] + exact Backends.Native.exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error + fuel selector switchId cases' + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots hSelector hFind hSelectorRange hTagsRange + +/-- The source-level switch cases emitted by `buildSwitch` for SimpleStorage +project to the concrete two-element selector list `[0x6057361d, 0x2e64cec1]`. +This anchors source-level selector-miss reasoning at the IR layer so the rest +of the dispatcher proof can stay parametric in `cases'`. -/ +private theorem simpleStorageBuildSwitchSourceCases_map_fst : + simpleStorageBuildSwitchSourceCases.map (·.1) = + [(0x6057361d : Nat), (0x2e64cec1 : Nat)] := rfl + +/-- Source-cases find?-none for SimpleStorage: the selector-miss assumption +`sel ≠ 0x6057361d ∧ sel ≠ 0x2e64cec1` (the two SimpleStorage IR selectors) +suffices to discharge `find?` on the buildSwitch-emitted source case list. +This is the source-level half of the selector-miss closed form. -/ +private theorem simpleStorageBuildSwitchSourceCases_find?_none {sel : Nat} + (h1 : sel ≠ 0x6057361d) (h2 : sel ≠ 0x2e64cec1) : + simpleStorageBuildSwitchSourceCases.find? (fun entry => entry.1 == sel) = + none := by + show ([_, _] : List _).find? _ = none + simp only [List.find?_cons, List.find?_nil] + have hb1 : ((0x6057361d : Nat) == sel) = false := + beq_eq_false_iff_ne.mpr (Ne.symm h1) + have hb2 : ((0x2e64cec1 : Nat) == sel) = false := + beq_eq_false_iff_ne.mpr (Ne.symm h2) + rw [hb1, hb2] + +/-- All tags in the buildSwitch-emitted source cases for SimpleStorage are +strictly less than `EvmYul.UInt256.size = 2^256`. The two source selectors +(`0x6057361d`, `0x2e64cec1`) both fit in 32 bits, far below the EVM word +modulus. -/ +private theorem simpleStorageBuildSwitchSourceCases_tags_lt_uint256_size : + ∀ tag body, (tag, body) ∈ simpleStorageBuildSwitchSourceCases → + tag < EvmYul.UInt256.size := by + intro tag body h + simp only [simpleStorageBuildSwitchSourceCases, simpleStorageIRContract, + List.map_cons, List.map_nil, List.mem_cons, Prod.mk.injEq, + List.not_mem_nil, or_false] at h + rcases h with ⟨rfl, _⟩ | ⟨rfl, _⟩ <;> decide + +/-- Shape characterization for the lowered SimpleStorage source switch cases. + +Exactly two entries — the SimpleStorage IR selectors `0x6057361d` and +`0x2e64cec1` — flow through `lowerSwitchCasesNativeWithSwitchIds`, so the +output `cases'` is forced to a two-element shape with lowered bodies. Each +selector tag is preserved unchanged by the lowering; only the case bodies +are recursively lowered. Hit-case proofs consume this shape to convert the +parametric `cases'` (opened from the `_sourceLowered` existential) into the +concrete `[(0x6057361d, _), (0x2e64cec1, _)]` form that matches the +generic harness lemmas like +`exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_fuel`. -/ +private theorem simpleStorageBuildSwitchSourceCases_lowered_shape + (reservedNames : List String) (nextSwitchId final : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (hLower : + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames nextSwitchId + simpleStorageBuildSwitchSourceCases = .ok (cases', final)) : + ∃ storeBody' retrieveBody', + cases' = [(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] := by + have hTags := Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq + _ _ _ _ _ hLower + have hLen := Backends.lowerSwitchCasesNativeWithSwitchIds_length_eq + _ _ _ _ _ hLower + rw [simpleStorageBuildSwitchSourceCases_map_fst] at hTags + match cases', hLen, hTags with + | [(t1, b1), (t2, b2)], _, hTags => + simp only [List.map_cons, List.map_nil, List.cons.injEq, and_true] at hTags + obtain ⟨ht1, ht2⟩ := hTags + exact ⟨b1, b2, by rw [ht1, ht2]⟩ + +/-- Lowered native body shape of the `store(uint256)` selector arm of the +SimpleStorage source switch cases (leading `.Block []` from the `dispatchBody` +comment, followed by callvalue/calldatasize guards and the calldataload/ +sstore/stop primitive sequence). Pinning this lets downstream hit-case proofs +specialize to a fixed concrete body instead of carrying a parametric +`storeBody'`. -/ +private def simpleStorageLoweredStoreCaseBody : List EvmYul.Yul.Ast.Stmt := + [EvmYul.Yul.Ast.Stmt.Block [], + .If (Backends.lowerExprNative (.call "callvalue" [])) + [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], + .If (Backends.lowerExprNative + (.call "lt" [.call "calldatasize" [], .lit 36])) + [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], + .Let ["value"] (some (Backends.lowerExprNative + (.call "calldataload" [.lit 4]))), + .ExprStmtCall (Backends.lowerExprNative + (.call "sstore" [.lit 0, .ident "value"])), + .ExprStmtCall (Backends.lowerExprNative (.call "stop" []))] + +/-- Lowered native body shape of the `retrieve()` selector arm of the +SimpleStorage source switch cases. Mirrors `simpleStorageLoweredStoreCaseBody` +for the source `mstore(0, sload(0)); return(0, 32)` body. -/ +private def simpleStorageLoweredRetrieveCaseBody : List EvmYul.Yul.Ast.Stmt := + [EvmYul.Yul.Ast.Stmt.Block [], + .If (Backends.lowerExprNative (.call "callvalue" [])) + [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], + .If (Backends.lowerExprNative + (.call "lt" [.call "calldatasize" [], .lit 4])) + [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], + .ExprStmtCall (Backends.lowerExprNative + (.call "mstore" [.lit 0, .call "sload" [.lit 0]])), + .ExprStmtCall (Backends.lowerExprNative + (.call "return" [.lit 0, .lit 32]))] + +/-- 5-statement tail of `simpleStorageLoweredStoreCaseBody`, with the leading +no-op `.Block []` (from the `dispatchBody` source comment) stripped. -/ +private def simpleStorageLoweredStoreCaseBodyTail : List EvmYul.Yul.Ast.Stmt := + [.If (Backends.lowerExprNative (.call "callvalue" [])) + [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], + .If (Backends.lowerExprNative + (.call "lt" [.call "calldatasize" [], .lit 36])) + [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], + .Let ["value"] (some (Backends.lowerExprNative + (.call "calldataload" [.lit 4]))), + .ExprStmtCall (Backends.lowerExprNative + (.call "sstore" [.lit 0, .ident "value"])), + .ExprStmtCall (Backends.lowerExprNative (.call "stop" []))] + +/-- 4-statement tail of `simpleStorageLoweredRetrieveCaseBody`, with the leading +no-op `.Block []` (from the `dispatchBody` source comment) stripped. -/ +private def simpleStorageLoweredRetrieveCaseBodyTail : List EvmYul.Yul.Ast.Stmt := + [.If (Backends.lowerExprNative (.call "callvalue" [])) + [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], + .If (Backends.lowerExprNative + (.call "lt" [.call "calldatasize" [], .lit 4])) + [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], + .ExprStmtCall (Backends.lowerExprNative + (.call "mstore" [.lit 0, .call "sload" [.lit 0]])), + .ExprStmtCall (Backends.lowerExprNative + (.call "return" [.lit 0, .lit 32]))] + +/-- Strip the leading `.Block []` no-op (a `dispatchBody` source-comment +artifact) from the lowered store-case body when proving a `.error err` +obligation. Combines `exec_block_nil_ok` (the empty inner block is a no-op at +positive fuel, returning the input state unchanged) with +`exec_block_cons_tail_error` (a successful head followed by an erroring tail +makes the whole block error). Reduces a 6-statement obligation to a strictly +smaller 5-statement tail obligation. -/ +private theorem exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error + (fuel' : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) (err : EvmYul.Yul.Exception) + (hTail : + EvmYul.Yul.exec (fuel' + 1) + (.Block simpleStorageLoweredStoreCaseBodyTail) codeOverride state = + .error err) : + EvmYul.Yul.exec (fuel' + 2) + (.Block simpleStorageLoweredStoreCaseBody) codeOverride state = + .error err := by + show EvmYul.Yul.exec (Nat.succ (fuel' + 1)) + (.Block (.Block [] :: simpleStorageLoweredStoreCaseBodyTail)) + codeOverride state = .error err + refine Backends.Native.exec_block_cons_tail_error (fuel' + 1) (.Block []) + simpleStorageLoweredStoreCaseBodyTail codeOverride state state err ?_ hTail + exact Backends.Native.exec_block_nil_ok fuel' codeOverride state + +/-- Retrieve-case dual of +`exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error`. -/ +private theorem exec_block_simpleStorageLoweredRetrieveCaseBody_head_strip_error + (fuel' : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) (err : EvmYul.Yul.Exception) + (hTail : + EvmYul.Yul.exec (fuel' + 1) + (.Block simpleStorageLoweredRetrieveCaseBodyTail) codeOverride state = + .error err) : + EvmYul.Yul.exec (fuel' + 2) + (.Block simpleStorageLoweredRetrieveCaseBody) codeOverride state = + .error err := by + show EvmYul.Yul.exec (Nat.succ (fuel' + 1)) + (.Block (.Block [] :: simpleStorageLoweredRetrieveCaseBodyTail)) + codeOverride state = .error err + refine Backends.Native.exec_block_cons_tail_error (fuel' + 1) (.Block []) + simpleStorageLoweredRetrieveCaseBodyTail codeOverride state state err ?_ hTail + exact Backends.Native.exec_block_nil_ok fuel' codeOverride state + +/-- 4-statement callvalue-stripped tail of `simpleStorageLoweredStoreCaseBody`, +with both the leading no-op `.Block []` and the leading `if callvalue() {…}` +revert guard removed. Used to further shrink the dispatcher hit-case body-exec +obligation when the transaction has zero `msgValue`. -/ +private def simpleStorageLoweredStoreCaseBodyTail2 : List EvmYul.Yul.Ast.Stmt := + [.If (Backends.lowerExprNative + (.call "lt" [.call "calldatasize" [], .lit 36])) + [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], + .Let ["value"] (some (Backends.lowerExprNative + (.call "calldataload" [.lit 4]))), + .ExprStmtCall (Backends.lowerExprNative + (.call "sstore" [.lit 0, .ident "value"])), + .ExprStmtCall (Backends.lowerExprNative (.call "stop" []))] + +/-- 3-statement calldatasize-stripped tail of +`simpleStorageLoweredStoreCaseBodyTail2`, with the argument-length revert guard +removed after proving the transaction supplies the setter argument. -/ +private def simpleStorageLoweredStoreCaseBodyTail3 : List EvmYul.Yul.Ast.Stmt := + [.Let ["value"] (some (Backends.lowerExprNative + (.call "calldataload" [.lit 4]))), + .ExprStmtCall (Backends.lowerExprNative + (.call "sstore" [.lit 0, .ident "value"])), + .ExprStmtCall (Backends.lowerExprNative (.call "stop" []))] + +/-- Closed-form native exec of the direct lowered setter body from the +generated dispatcher marked-prefix state. + +This is the direct-body counterpart of the SimpleStorage hit-case theorem below: +it works for any lowered native contract and any switch temporary store because +the body reads calldata and writes storage through the shared state. -/ +private theorem exec_block_store0_calldataload4_stop_markedPrefix_halt + (fuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (arg : Nat) (rest : List Nat) (hArgs : tx.args = arg :: rest) : + let initialWithStore := + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + contract tx storage observableSlots switchId store + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let finalState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + EvmYul.Yul.exec (fuel + 10) + (.Block simpleStorageLoweredStoreCaseBodyTail3) + (some contract) initialWithStore = + .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by + intro initialWithStore withValue finalState + have hWord : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + contract tx storage observableSlots).sharedState.calldataload + (EvmYul.UInt256.ofNat 4) = + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg := by + exact + Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataload4_arg0_word + contract tx storage observableSlots arg rest hArgs + simp [simpleStorageLoweredStoreCaseBodyTail3, Backends.lowerExprNative, + Backends.lookupRuntimePrimOp, EvmYul.Yul.exec, EvmYul.Yul.eval, + EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, EvmYul.Yul.execPrimCall, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.State.multifill, initialWithStore, withValue, finalState, + hWord, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert, GetElem?.getElem!, decidableGetElem?, + GetElem.getElem, EvmYul.Yul.State.store, EvmYul.Yul.State.lookup!] + have hPerm : + (EvmYul.Yul.State.Ok + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + contract tx storage observableSlots).sharedState + (((store.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)).insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg))).executionEnv.perm = + true := by + rfl + rw [show fuel + 7 = (fuel + 6) + 1 by omega] + rw [Compiler.Proofs.YulGeneration.Backends.Native.primCall_sstore_ok + (fuel + 6) _ _ _ hPerm] + rfl + +/-- 3-statement callvalue-stripped tail of `simpleStorageLoweredRetrieveCaseBody`. -/ +private def simpleStorageLoweredRetrieveCaseBodyTail2 : List EvmYul.Yul.Ast.Stmt := + [.If (Backends.lowerExprNative + (.call "lt" [.call "calldatasize" [], .lit 4])) + [.ExprStmtCall (Backends.lowerExprNative (.call "revert" [.lit 0, .lit 0]))], + .ExprStmtCall (Backends.lowerExprNative + (.call "mstore" [.lit 0, .call "sload" [.lit 0]])), + .ExprStmtCall (Backends.lowerExprNative + (.call "return" [.lit 0, .lit 32]))] + +/-- 2-statement lt-calldatasize-stripped tail of +`simpleStorageLoweredRetrieveCaseBodyTail2`, with both the callvalue revert +guard and the inner `if lt(calldatasize, 4) {…}` argument-length revert +guard removed. Used to further shrink the dispatcher hit-case body-exec +obligation when the calldata is at least 4 bytes (which is automatic for any +ABI-conforming call since the selector itself is 4 bytes). -/ +private def simpleStorageLoweredRetrieveCaseBodyTail3 : List EvmYul.Yul.Ast.Stmt := + [.ExprStmtCall (Backends.lowerExprNative + (.call "mstore" [.lit 0, .call "sload" [.lit 0]])), + .ExprStmtCall (Backends.lowerExprNative + (.call "return" [.lit 0, .lit 32]))] + +private def loweredLiteralReturnCaseBodyTail (value : Nat) : + List EvmYul.Yul.Ast.Stmt := + [.ExprStmtCall (Backends.lowerExprNative + (.call "mstore" [.lit 0, .lit value])), + .ExprStmtCall (Backends.lowerExprNative + (.call "return" [.lit 0, .lit 32]))] + +private def loweredZeroParamLiteralReturnCaseBody (value : Nat) : + List EvmYul.Yul.Ast.Stmt := + .If (Backends.lowerExprNative + (.call "lt" [.call "calldatasize" [], .lit 4])) + [.ExprStmtCall (Backends.lowerExprNative + (.call "revert" [.lit 0, .lit 0]))] :: + loweredLiteralReturnCaseBodyTail value + +private def loweredZeroParamSload0ReturnCaseBody : + List EvmYul.Yul.Ast.Stmt := + .If (Backends.lowerExprNative + (.call "lt" [.call "calldatasize" [], .lit 4])) + [.ExprStmtCall (Backends.lowerExprNative + (.call "revert" [.lit 0, .lit 0]))] :: + simpleStorageLoweredRetrieveCaseBodyTail3 + +private def loweredCalldataload4ReturnCaseBodyTail : + List EvmYul.Yul.Ast.Stmt := + [.ExprStmtCall (Backends.lowerExprNative + (.call "mstore" [.lit 0, .call "calldataload" [.lit 4]])), + .ExprStmtCall (Backends.lowerExprNative + (.call "return" [.lit 0, .lit 32]))] + +private def loweredCalldataloadReturnCaseBodyTail (idx : Nat) : + List EvmYul.Yul.Ast.Stmt := + [.ExprStmtCall (Backends.lowerExprNative + (.call "mstore" [.lit 0, + .call "calldataload" [.lit (4 + 32 * idx)]])), + .ExprStmtCall (Backends.lowerExprNative + (.call "return" [.lit 0, .lit 32]))] + +/-- Strip the leading `if callvalue() { revert(0,0) }` guard from +`simpleStorageLoweredStoreCaseBodyTail` when proving a `.error err` +obligation, given that the current `executionEnv.weiValue` is zero (the +canonical zero literal). Combines the harness skip lemma +`exec_if_lowerExprNative_callvalue_skip_zero_fuel` (the callvalue guard +is a no-op at zero `weiValue`) with `exec_block_cons_tail_error` (a +successful head followed by an erroring tail makes the whole block +error). Reduces a 5-statement tail obligation to a 4-statement +callvalue-stripped tail2 obligation. -/ +private theorem exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (err : EvmYul.Yul.Exception) + (hWei : shared.executionEnv.weiValue = (⟨0⟩ : EvmYul.Literal)) + (hTail2 : + EvmYul.Yul.exec (fuel + 7) (.Block simpleStorageLoweredStoreCaseBodyTail2) + codeOverride (.Ok shared store) = .error err) : + EvmYul.Yul.exec (fuel + 8) (.Block simpleStorageLoweredStoreCaseBodyTail) + codeOverride (.Ok shared store) = .error err := by + show EvmYul.Yul.exec (Nat.succ (fuel + 7)) + (.Block ((simpleStorageLoweredStoreCaseBodyTail).head! :: + simpleStorageLoweredStoreCaseBodyTail2)) + codeOverride (.Ok shared store) = .error err + refine Backends.Native.exec_block_cons_tail_error (fuel + 7) _ + simpleStorageLoweredStoreCaseBodyTail2 codeOverride + (.Ok shared store) (.Ok shared store) err ?_ hTail2 + show EvmYul.Yul.exec ((fuel + 1) + 6) + (.If (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + [.ExprStmtCall (Backends.lowerExprNative + (.call "revert" [.lit 0, .lit 0]))]) + codeOverride (.Ok shared store) = .ok (.Ok shared store) + exact Backends.Native.exec_if_lowerExprNative_callvalue_skip_zero_fuel + (fuel + 1) _ codeOverride shared store hWei + +/-- Retrieve-case dual of +`exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error`. -/ +private theorem exec_block_simpleStorageLoweredRetrieveCaseBodyTail_callvalue_strip_error + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (err : EvmYul.Yul.Exception) + (hWei : shared.executionEnv.weiValue = (⟨0⟩ : EvmYul.Literal)) + (hTail2 : + EvmYul.Yul.exec (fuel + 6) + (.Block simpleStorageLoweredRetrieveCaseBodyTail2) + codeOverride (.Ok shared store) = .error err) : + EvmYul.Yul.exec (fuel + 7) (.Block simpleStorageLoweredRetrieveCaseBodyTail) + codeOverride (.Ok shared store) = .error err := by + show EvmYul.Yul.exec (Nat.succ (fuel + 6)) + (.Block ((simpleStorageLoweredRetrieveCaseBodyTail).head! :: + simpleStorageLoweredRetrieveCaseBodyTail2)) + codeOverride (.Ok shared store) = .error err + refine Backends.Native.exec_block_cons_tail_error (fuel + 6) _ + simpleStorageLoweredRetrieveCaseBodyTail2 codeOverride + (.Ok shared store) (.Ok shared store) err ?_ hTail2 + show EvmYul.Yul.exec ((fuel) + 6) + (.If (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + [.ExprStmtCall (Backends.lowerExprNative + (.call "revert" [.lit 0, .lit 0]))]) + codeOverride (.Ok shared store) = .ok (.Ok shared store) + exact Backends.Native.exec_if_lowerExprNative_callvalue_skip_zero_fuel + fuel _ codeOverride shared store hWei + +/-- Strip the leading `if lt(calldatasize(), 4) { revert(0,0) }` argument-length +guard from `simpleStorageLoweredRetrieveCaseBodyTail2` when proving a +`.error err` obligation, given that the current calldata has at least 4 +bytes (the selector). Combines the harness skip lemma +`exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel` with +`exec_block_cons_tail_error`. Reduces a 3-statement tail2 obligation to a +2-statement lt-stripped tail3 obligation. -/ +private theorem exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (err : EvmYul.Yul.Exception) + (hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size) + (hGe : 4 ≤ shared.executionEnv.calldata.size) + (hTail3 : + EvmYul.Yul.exec (fuel + 9) + (.Block simpleStorageLoweredRetrieveCaseBodyTail3) + codeOverride (.Ok shared store) = .error err) : + EvmYul.Yul.exec (fuel + 10) + (.Block simpleStorageLoweredRetrieveCaseBodyTail2) + codeOverride (.Ok shared store) = .error err := by + show EvmYul.Yul.exec (Nat.succ (fuel + 9)) + (.Block ((simpleStorageLoweredRetrieveCaseBodyTail2).head! :: + simpleStorageLoweredRetrieveCaseBodyTail3)) + codeOverride (.Ok shared store) = .error err + refine Backends.Native.exec_block_cons_tail_error (fuel + 9) _ + simpleStorageLoweredRetrieveCaseBodyTail3 codeOverride + (.Ok shared store) (.Ok shared store) err ?_ hTail3 + show EvmYul.Yul.exec (fuel + 9) + (.If (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit 4])) + [.ExprStmtCall (Backends.lowerExprNative + (.call "revert" [.lit 0, .lit 0]))]) + codeOverride (.Ok shared store) = .ok (.Ok shared store) + exact Backends.Native.exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel + fuel _ codeOverride shared store 4 hSize (by decide) hGe + +/-- Store-case dual of +`exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error`, with +the ABI argument guard threshold `36 = 4 + 32`. -/ +private theorem exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (err : EvmYul.Yul.Exception) + (hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size) + (hGe : 36 ≤ shared.executionEnv.calldata.size) + (hTail3 : + EvmYul.Yul.exec (fuel + 10) + (.Block simpleStorageLoweredStoreCaseBodyTail3) + codeOverride (.Ok shared store) = .error err) : + EvmYul.Yul.exec (fuel + 11) + (.Block simpleStorageLoweredStoreCaseBodyTail2) + codeOverride (.Ok shared store) = .error err := by + show EvmYul.Yul.exec (Nat.succ (fuel + 10)) + (.Block ((simpleStorageLoweredStoreCaseBodyTail2).head! :: + simpleStorageLoweredStoreCaseBodyTail3)) + codeOverride (.Ok shared store) = .error err + refine Backends.Native.exec_block_cons_tail_error (fuel + 10) _ + simpleStorageLoweredStoreCaseBodyTail3 codeOverride + (.Ok shared store) (.Ok shared store) err ?_ hTail3 + show EvmYul.Yul.exec (fuel + 10) + (.If (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit 36])) + [.ExprStmtCall (Backends.lowerExprNative + (.call "revert" [.lit 0, .lit 0]))]) + codeOverride (.Ok shared store) = .ok (.Ok shared store) + exact Backends.Native.exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel + (fuel + 1) _ codeOverride shared store 36 hSize (by decide) hGe + +/-- Closed-form native exec of the store payload +`let value := calldataload(4); sstore(0, value); stop` for an arbitrary +shared state/store once the calldata word is known. -/ +private theorem exec_block_store0_calldataload4_stop_shared_halt + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (arg : Nat) + (hPerm : shared.executionEnv.perm = true) + (hWord : + shared.calldataload (EvmYul.UInt256.ofNat 4) = + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) : + let initialWithStore : EvmYul.Yul.State := .Ok shared store + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let finalState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + EvmYul.Yul.exec (fuel + 10) + (.Block simpleStorageLoweredStoreCaseBodyTail3) + codeOverride initialWithStore = + .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by + intro initialWithStore withValue finalState + simp [simpleStorageLoweredStoreCaseBodyTail3, Backends.lowerExprNative, + Backends.lookupRuntimePrimOp, EvmYul.Yul.exec, EvmYul.Yul.eval, + EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, EvmYul.Yul.execPrimCall, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.State.multifill, initialWithStore, withValue, finalState, + hWord, EvmYul.Yul.State.insert, GetElem?.getElem!, decidableGetElem?, + GetElem.getElem, EvmYul.Yul.State.store, EvmYul.Yul.State.lookup!] + have hPerm : + (EvmYul.Yul.State.Ok shared + (Finmap.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + store)).executionEnv.perm = true := by + simpa [EvmYul.Yul.State.executionEnv] using hPerm + rw [show fuel + 7 = (fuel + 6) + 1 by omega] + rw [Compiler.Proofs.YulGeneration.Backends.Native.primCall_sstore_ok + (fuel + 6) _ _ _ hPerm] + rfl + +private theorem exec_block_store0_calldataload4_stop_shared_halt_tight + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (arg : Nat) + (hPerm : shared.executionEnv.perm = true) + (hWord : + shared.calldataload (EvmYul.UInt256.ofNat 4) = + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) : + let initialWithStore : EvmYul.Yul.State := .Ok shared store + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let finalState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + EvmYul.Yul.exec (fuel + 9) + (.Block simpleStorageLoweredStoreCaseBodyTail3) + codeOverride initialWithStore = + .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by + intro initialWithStore withValue finalState + simp [simpleStorageLoweredStoreCaseBodyTail3, Backends.lowerExprNative, + Backends.lookupRuntimePrimOp, EvmYul.Yul.exec, EvmYul.Yul.eval, + EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, EvmYul.Yul.execPrimCall, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.State.multifill, initialWithStore, withValue, finalState, + hWord, EvmYul.Yul.State.insert, GetElem?.getElem!, decidableGetElem?, + GetElem.getElem, EvmYul.Yul.State.store, EvmYul.Yul.State.lookup!] + have hPerm' : + (EvmYul.Yul.State.Ok shared + (Finmap.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + store)).executionEnv.perm = true := by + simpa [EvmYul.Yul.State.executionEnv] using hPerm + rw [show fuel + 6 = (fuel + 5) + 1 by omega] + rw [Compiler.Proofs.YulGeneration.Backends.Native.primCall_sstore_ok + (fuel + 5) _ _ _ hPerm'] + rfl + +private theorem exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error_tight + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (err : EvmYul.Yul.Exception) + (hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size) + (hGe : 36 ≤ shared.executionEnv.calldata.size) + (hTail3 : + EvmYul.Yul.exec (fuel + 9) + (.Block simpleStorageLoweredStoreCaseBodyTail3) + codeOverride (.Ok shared store) = .error err) : + EvmYul.Yul.exec (fuel + 10) + (.Block simpleStorageLoweredStoreCaseBodyTail2) + codeOverride (.Ok shared store) = .error err := by + show EvmYul.Yul.exec (Nat.succ (fuel + 9)) + (.Block ((simpleStorageLoweredStoreCaseBodyTail2).head! :: + simpleStorageLoweredStoreCaseBodyTail3)) + codeOverride (.Ok shared store) = .error err + refine Backends.Native.exec_block_cons_tail_error (fuel + 9) _ + simpleStorageLoweredStoreCaseBodyTail3 codeOverride + (.Ok shared store) (.Ok shared store) err ?_ hTail3 + show EvmYul.Yul.exec (fuel + 9) + (.If (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit 36])) + [.ExprStmtCall (Backends.lowerExprNative + (.call "revert" [.lit 0, .lit 0]))]) + codeOverride (.Ok shared store) = .ok (.Ok shared store) + exact Backends.Native.exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel + fuel _ codeOverride shared store 36 hSize (by decide) hGe + +/-- Closed-form native exec of the generated one-argument setter body from the +generated dispatcher marked-prefix state. -/ +private theorem exec_block_simpleStorageLoweredStoreCaseBodyTail2_markedPrefix_halt + (fuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (arg : Nat) (rest : List Nat) (hArgs : tx.args = arg :: rest) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + let markedStore := + (((store.insert (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + contract tx storage observableSlots).sharedState + let initialWithStore : EvmYul.Yul.State := .Ok shared markedStore + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let finalState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + EvmYul.Yul.exec (fuel + 10) + (.Block simpleStorageLoweredStoreCaseBodyTail2) + (some contract) initialWithStore = + .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by + intro markedStore shared initialWithStore withValue finalState + have hWord : + shared.calldataload (EvmYul.UInt256.ofNat 4) = + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg := by + simpa [shared, EvmYul.Yul.State.toState] using + Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataload4_arg0_word + contract tx storage observableSlots arg rest hArgs + have hTail3 : + EvmYul.Yul.exec (fuel + 9) + (.Block simpleStorageLoweredStoreCaseBodyTail3) + (some contract) initialWithStore = + .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by + have hPerm : shared.executionEnv.perm = true := by + simp [shared, Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + simpa [initialWithStore, withValue, finalState] using + exec_block_store0_calldataload4_stop_shared_halt_tight + fuel (some contract) shared markedStore arg hPerm hWord + have hCalldataSize : + shared.executionEnv.calldata.size = 4 + tx.args.length * 32 := by + simpa [shared, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + EvmYul.Yul.State.sharedState, EvmYul.Yul.State.insert] using + (Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId_calldata_size + contract tx storage observableSlots switchId store) + have hSize : + shared.executionEnv.calldata.size < EvmYul.UInt256.size := by + simpa [hCalldataSize] using hNoWrap + have hGe : + 36 ≤ shared.executionEnv.calldata.size := by + rw [hCalldataSize, hArgs] + simp + omega + simpa [initialWithStore] using + exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error_tight + fuel (some contract) shared markedStore + (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) hSize hGe hTail3 + +/-- Store-case argument-length guard fires when calldata contains only the +selector. This is the short-calldata counterpart to +`exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error`. -/ +private theorem exec_block_simpleStorageLoweredStoreCaseBodyTail2_short_revert + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hSizeEq : shared.executionEnv.calldata.size = 4) : + EvmYul.Yul.exec (fuel + 11) + (.Block simpleStorageLoweredStoreCaseBodyTail2) + codeOverride (.Ok shared store) = + .error EvmYul.Yul.Exception.Revert := by + show EvmYul.Yul.exec (Nat.succ (fuel + 10)) + (.Block ((simpleStorageLoweredStoreCaseBodyTail2).head! :: + simpleStorageLoweredStoreCaseBodyTail3)) + codeOverride (.Ok shared store) = .error EvmYul.Yul.Exception.Revert + refine Backends.Native.exec_block_cons_error (fuel + 10) _ + simpleStorageLoweredStoreCaseBodyTail3 codeOverride + (.Ok shared store) EvmYul.Yul.Exception.Revert ?_ + refine Backends.Native.exec_if_eval_nonzero_error (fuel + 9) _ _ + codeOverride (.Ok shared store) (.Ok shared store) + (EvmYul.UInt256.ofNat 1) EvmYul.Yul.Exception.Revert ?_ ?_ ?_ + · rw [Backends.Native.eval_lowerExprNative_lt_calldatasize_ok_fuel] + simp [hSizeEq, EvmYul.UInt256.lt, EvmYul.UInt256.ofNat, Fin.ofNat, + EvmYul.UInt256.size] + decide + · change (EvmYul.UInt256.ofNat 1 : EvmYul.UInt256) ≠ ⟨0⟩ + decide + · simpa [Backends.Native.nativeRevertZeroZeroStmt, Backends.lowerExprNative, + Backends.lookupRuntimePrimOp] using + (Backends.Native.exec_block_cons_error (fuel + 8) + Backends.Native.nativeRevertZeroZeroStmt [] codeOverride + (.Ok shared store) EvmYul.Yul.Exception.Revert + (Backends.Native.exec_revert_zero_zero_error (fuel + 2) + (.Ok shared store) codeOverride)) + +/-- Closed-form native exec of the store hit-case 3-statement payload + `let value := calldataload(4); sstore(0, value); stop` after the + callvalue and argument-length guards have been stripped. -/ +private theorem exec_block_simpleStorageLoweredStoreCaseBodyTail3_halt + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) + (arg : Nat) (rest : List Nat) (hArgs : tx.args = arg :: rest) : + let initialWithStore : EvmYul.Yul.State := + .Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState store + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let finalState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + EvmYul.Yul.exec (fuel + 10) + (.Block simpleStorageLoweredStoreCaseBodyTail3) + codeOverride initialWithStore = + .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by + intro initialWithStore withValue finalState + have hWord : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.calldataload (EvmYul.UInt256.ofNat 4) = + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg := by + simpa [EvmYul.Yul.State.toState] using + Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataload4_arg0_word + Compiler.SimpleStorageNativeWitness.nativeContract tx storage observableSlots + arg rest hArgs + simp [simpleStorageLoweredStoreCaseBodyTail3, Backends.lowerExprNative, + Backends.lookupRuntimePrimOp, EvmYul.Yul.exec, EvmYul.Yul.eval, + EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, EvmYul.Yul.execPrimCall, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.State.multifill, initialWithStore, withValue, finalState, + hWord, EvmYul.Yul.State.insert, GetElem?.getElem!, decidableGetElem?, + GetElem.getElem, EvmYul.Yul.State.store, EvmYul.Yul.State.lookup!] + have hPerm : + (EvmYul.Yul.State.Ok + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState + (Finmap.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + store)).executionEnv.perm = true := by + rfl + rw [show fuel + 7 = (fuel + 6) + 1 by omega] + rw [Compiler.Proofs.YulGeneration.Backends.Native.primCall_sstore_ok + (fuel + 6) _ _ _ hPerm] + rfl + +/-- Composed body-level closed form for the SimpleStorage store hit-case when +the calldata contains the setter argument. -/ +private theorem exec_block_simpleStorageLoweredStoreCaseBody_halt + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) + (arg : Nat) (rest : List Nat) (hArgs : tx.args = arg :: rest) + (hWei : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.weiValue = + (⟨0⟩ : EvmYul.Literal)) + (hSize : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.calldata.size < + EvmYul.UInt256.size) + (hGe : + 36 ≤ (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.calldata.size) : + let initialWithStore : EvmYul.Yul.State := + .Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState store + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let finalState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + EvmYul.Yul.exec (fuel + 13) (.Block simpleStorageLoweredStoreCaseBody) + codeOverride initialWithStore = + .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by + intro initialWithStore withValue finalState + have hTail3 := exec_block_simpleStorageLoweredStoreCaseBodyTail3_halt + fuel codeOverride tx storage observableSlots store arg rest hArgs + have hTail2 := exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error + fuel codeOverride + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState + store _ hSize hGe hTail3 + have hTail := exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error + (fuel + 4) codeOverride + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState + store _ hWei hTail2 + exact exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error + (fuel + 11) codeOverride initialWithStore _ hTail + +/-- Closed-form native exec of the retrieve hit-case 2-statement payload + `mstore(0, sload(0)) ; return(0, 32)`. EVMYulLean models `RETURN` as a + halt error; the exec composes the harness's exec-side + `mstore(lit, sload(lit))` seam with the exec-side `return(lit, lit)` + halt seam through `exec_block_cons_tail_error`. The resulting halt state + threads (i) storage-access tracking from the SLOAD on slot zero, + (ii) the memory write of the loaded word at offset zero, and + (iii) the post-`evmReturn` machine state holding the 32-byte return + buffer. Discharges the `hTail3` premise of + `exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error` + unconditionally — no extra calldata/wei hypotheses needed because the + payload reads only from storage and writes only to memory. -/ +private theorem exec_block_simpleStorageLoweredRetrieveCaseBodyTail3_closed + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) : + EvmYul.Yul.exec (fuel + 9) + (.Block simpleStorageLoweredRetrieveCaseBodyTail3) + codeOverride (.Ok shared store) = + let (state', value) := shared.sload (EvmYul.UInt256.ofNat 0) + let shared1 : EvmYul.SharedState .Yul := { shared with toState := state' } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } + let shared3 : EvmYul.SharedState .Yul := + { shared2 with + toMachineState := + shared2.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + .error (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store) ⟨1⟩) := by + show EvmYul.Yul.exec (Nat.succ (fuel + 8)) + (.Block ((simpleStorageLoweredRetrieveCaseBodyTail3).head! :: + [(simpleStorageLoweredRetrieveCaseBodyTail3).getLast!])) + codeOverride (.Ok shared store) = _ + refine Backends.Native.exec_block_cons_tail_error (fuel + 8) _ _ codeOverride + (.Ok shared store) _ _ + (Backends.Native.exec_lowerExprNative_mstore_lit_sload_lit_ok_fuel + fuel shared store codeOverride 0 0) ?_ + -- Tail [return(0, 32)] errors via the singleton-return harness lemma. + have hSeam := + Backends.Native.exec_block_singleton_lowerExprNative_return_lit_lit_error_fuel + (fuel + 1) + ({ ({ shared with toState := (shared.sload (EvmYul.UInt256.ofNat 0)).1 } + : EvmYul.SharedState .Yul) with + toMachineState := + ({ shared with toState := (shared.sload (EvmYul.UInt256.ofNat 0)).1 } + : EvmYul.SharedState .Yul).toMachineState.mstore + (EvmYul.UInt256.ofNat 0) (shared.sload (EvmYul.UInt256.ofNat 0)).2 }) + store codeOverride 0 32 + have hF : (fuel + 1) + 7 = fuel + 8 := by omega + rw [hF] at hSeam + simpa [simpleStorageLoweredRetrieveCaseBodyTail3] using hSeam + +/-- Closed-form native exec of the generated scalar-return payload + `mstore(0, value); return(0, 32)` when the returned word is a literal. -/ +private theorem exec_block_loweredLiteralReturnCaseBodyTail_closed + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (value : Nat) : + EvmYul.Yul.exec (fuel + 8) + (.Block (loweredLiteralReturnCaseBodyTail value)) + codeOverride (.Ok shared store) = + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat value) } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + .error (EvmYul.Yul.Exception.YulHalt (.Ok shared2 store) ⟨1⟩) := by + show EvmYul.Yul.exec (Nat.succ (fuel + 7)) + (.Block ((loweredLiteralReturnCaseBodyTail value).head! :: + [(loweredLiteralReturnCaseBodyTail value).getLast!])) + codeOverride (.Ok shared store) = _ + refine Backends.Native.exec_block_cons_tail_error (fuel + 7) _ _ codeOverride + (.Ok shared store) _ _ + (by + have hHead := + Backends.Native.exec_lowerExprNative_mstore_lit_lit_ok_fuel + (fuel + 1) shared store codeOverride 0 value + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hHead) ?_ + have hSeam := + Backends.Native.exec_block_singleton_lowerExprNative_return_lit_lit_error_fuel + fuel + ({ shared with + toMachineState := + shared.toMachineState.mstore + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat value) }) + store codeOverride 0 32 + simpa [loweredLiteralReturnCaseBodyTail] using hSeam + +/-- Closed-form native exec of the generated zero-parameter scalar-return body. + The body includes `genParamLoads []`'s leading calldata-size guard before + the literal-return payload. -/ +private theorem exec_block_loweredZeroParamLiteralReturnCaseBody_closed + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (value : Nat) + (hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size) + (hGe : 4 ≤ shared.executionEnv.calldata.size) : + EvmYul.Yul.exec (fuel + 10) + (.Block (loweredZeroParamLiteralReturnCaseBody value)) + codeOverride (.Ok shared store) = + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat value) } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + .error (EvmYul.Yul.Exception.YulHalt (.Ok shared2 store) ⟨1⟩) := by + show EvmYul.Yul.exec (Nat.succ (fuel + 9)) + (.Block ((loweredZeroParamLiteralReturnCaseBody value).head! :: + loweredLiteralReturnCaseBodyTail value)) + codeOverride (.Ok shared store) = _ + refine Backends.Native.exec_block_cons_tail_error (fuel + 9) _ + (loweredLiteralReturnCaseBodyTail value) codeOverride + (.Ok shared store) (.Ok shared store) _ ?_ ?_ + · show EvmYul.Yul.exec (fuel + 9) + (.If (Backends.lowerExprNative + (.call "lt" [.call "calldatasize" [], .lit 4])) + [.ExprStmtCall (Backends.lowerExprNative + (.call "revert" [.lit 0, .lit 0]))]) + codeOverride (.Ok shared store) = .ok (.Ok shared store) + exact Backends.Native.exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel + fuel _ codeOverride shared store 4 hSize (by decide) hGe + · have hTail := + exec_block_loweredLiteralReturnCaseBodyTail_closed + (fuel + 1) codeOverride shared store value + rw [show fuel + 1 + 8 = fuel + 9 by omega] at hTail + simpa using hTail + +/-- Closed-form native exec of the generated zero-parameter storage-return body. + The body includes `genParamLoads []`'s leading calldata-size guard before + the `mstore(0, sload(0)); return(0, 32)` payload. -/ +private theorem exec_block_loweredZeroParamSload0ReturnCaseBody_closed + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size) + (hGe : 4 ≤ shared.executionEnv.calldata.size) : + EvmYul.Yul.exec (fuel + 10) + (.Block loweredZeroParamSload0ReturnCaseBody) + codeOverride (.Ok shared store) = + let (state', value) := shared.sload (EvmYul.UInt256.ofNat 0) + let shared1 : EvmYul.SharedState .Yul := { shared with toState := state' } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } + let shared3 : EvmYul.SharedState .Yul := + { shared2 with + toMachineState := + shared2.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + .error (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store) ⟨1⟩) := by + show EvmYul.Yul.exec (Nat.succ (fuel + 9)) + (.Block ((loweredZeroParamSload0ReturnCaseBody).head! :: + simpleStorageLoweredRetrieveCaseBodyTail3)) + codeOverride (.Ok shared store) = _ + refine Backends.Native.exec_block_cons_tail_error (fuel + 9) _ + simpleStorageLoweredRetrieveCaseBodyTail3 codeOverride + (.Ok shared store) (.Ok shared store) _ ?_ ?_ + · show EvmYul.Yul.exec (fuel + 9) + (.If (Backends.lowerExprNative + (.call "lt" [.call "calldatasize" [], .lit 4])) + [.ExprStmtCall (Backends.lowerExprNative + (.call "revert" [.lit 0, .lit 0]))]) + codeOverride (.Ok shared store) = .ok (.Ok shared store) + exact Backends.Native.exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel + fuel _ codeOverride shared store 4 hSize (by decide) hGe + · have hTail := + exec_block_simpleStorageLoweredRetrieveCaseBodyTail3_closed + fuel codeOverride shared store + simpa using hTail + +/-- Closed-form native exec of the generated single-argument scalar-return + payload `mstore(0, calldataload(4)); return(0, 32)`. -/ +private theorem exec_block_loweredCalldataload4ReturnCaseBodyTail_closed + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (arg : Nat) + (hWord : shared.calldataload (EvmYul.UInt256.ofNat 4) = + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) : + EvmYul.Yul.exec (fuel + 9) + (.Block loweredCalldataload4ReturnCaseBodyTail) + codeOverride (.Ok shared store) = + let value := Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + .error (EvmYul.Yul.Exception.YulHalt (.Ok shared2 store) ⟨1⟩) := by + show EvmYul.Yul.exec (Nat.succ (fuel + 8)) + (.Block ((loweredCalldataload4ReturnCaseBodyTail).head! :: + [(loweredCalldataload4ReturnCaseBodyTail).getLast!])) + codeOverride (.Ok shared store) = _ + refine Backends.Native.exec_block_cons_tail_error (fuel + 8) _ _ codeOverride + (.Ok shared store) _ _ + (by + have hHead := + Backends.Native.exec_lowerExprNative_mstore_lit_calldataload_lit_ok_fuel + fuel shared store codeOverride 0 4 + simpa [hWord] using hHead) ?_ + have hSeam := + Backends.Native.exec_block_singleton_lowerExprNative_return_lit_lit_error_fuel + (fuel + 1) + ({ shared with + toMachineState := + shared.toMachineState.mstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) }) + store codeOverride 0 32 + have hF : (fuel + 1) + 7 = fuel + 8 := by omega + rw [hF] at hSeam + simpa [loweredCalldataload4ReturnCaseBodyTail] using hSeam + +/-- Closed-form native exec of the generated aligned-argument scalar-return + payload `mstore(0, calldataload(4 + 32*idx)); return(0, 32)`. -/ +private theorem exec_block_loweredCalldataloadReturnCaseBodyTail_closed + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (idx arg : Nat) + (hWord : shared.calldataload (EvmYul.UInt256.ofNat (4 + 32 * idx)) = + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) : + EvmYul.Yul.exec (fuel + 9) + (.Block (loweredCalldataloadReturnCaseBodyTail idx)) + codeOverride (.Ok shared store) = + let value := Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + .error (EvmYul.Yul.Exception.YulHalt (.Ok shared2 store) ⟨1⟩) := by + show EvmYul.Yul.exec (Nat.succ (fuel + 8)) + (.Block ((loweredCalldataloadReturnCaseBodyTail idx).head! :: + [(loweredCalldataloadReturnCaseBodyTail idx).getLast!])) + codeOverride (.Ok shared store) = _ + refine Backends.Native.exec_block_cons_tail_error (fuel + 8) _ _ codeOverride + (.Ok shared store) _ _ + (by + have hHead := + Backends.Native.exec_lowerExprNative_mstore_lit_calldataload_lit_ok_fuel + fuel shared store codeOverride 0 (4 + 32 * idx) + simpa [hWord] using hHead) ?_ + have hSeam := + Backends.Native.exec_block_singleton_lowerExprNative_return_lit_lit_error_fuel + (fuel + 1) + ({ shared with + toMachineState := + shared.toMachineState.mstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) }) + store codeOverride 0 32 + have hF : (fuel + 1) + 7 = fuel + 8 := by omega + rw [hF] at hSeam + simpa [loweredCalldataloadReturnCaseBodyTail] using hSeam + +/-- Composed body-level closed form for the SimpleStorage retrieve hit-case. +Stacks the three guard-strip lemmas (head no-op, callvalue, lt-calldatasize) +on top of `_Tail3_closed` to characterize the full lowered retrieve body's +exec output as the closed-form halt error produced by +`mstore(0, sload(0)); return(0, 32)`. The `shared3` form mirrors `_Tail3_closed`. -/ +private theorem exec_block_simpleStorageLoweredRetrieveCaseBody_halt + (fuel : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hWei : shared.executionEnv.weiValue = (⟨0⟩ : EvmYul.Literal)) + (hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size) + (hGe : 4 ≤ shared.executionEnv.calldata.size) : + EvmYul.Yul.exec (fuel + 12) (.Block simpleStorageLoweredRetrieveCaseBody) + codeOverride (.Ok shared store) = + let (state', value) := shared.sload (EvmYul.UInt256.ofNat 0) + let shared1 : EvmYul.SharedState .Yul := { shared with toState := state' } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } + let shared3 : EvmYul.SharedState .Yul := + { shared2 with + toMachineState := + shared2.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + .error (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store) ⟨1⟩) := by + have hTail3 := exec_block_simpleStorageLoweredRetrieveCaseBodyTail3_closed + fuel codeOverride shared store + have hTail2 := exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error + fuel codeOverride shared store _ hSize hGe hTail3 + have hTail := exec_block_simpleStorageLoweredRetrieveCaseBodyTail_callvalue_strip_error + (fuel + 4) codeOverride shared store _ hWei hTail2 + exact exec_block_simpleStorageLoweredRetrieveCaseBody_head_strip_error + (fuel + 10) codeOverride (.Ok shared store) _ hTail + +/-- Concrete characterization of the lowered SimpleStorage source switch +cases. Both bodies are straight-line, so the lowering is deterministic and +the threaded `nextSwitchId` returns unchanged. Strengthens `_lowered_shape` +from a two-element shape with unspecified bodies to a fixed shape with +explicit lowered bodies, anchoring downstream hit-case proofs against the +harness primitive-call lemmas. -/ +private theorem simpleStorageBuildSwitchSourceCases_lowered_concrete + (reservedNames : List String) (nextSwitchId : Nat) : + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames nextSwitchId + simpleStorageBuildSwitchSourceCases = + .ok ([(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)], + nextSwitchId) := by + simp only [simpleStorageLoweredStoreCaseBody, + simpleStorageLoweredRetrieveCaseBody, + simpleStorageBuildSwitchSourceCases, simpleStorageIRContract, + Compiler.CodegenCommon.dispatchBody, + Compiler.CodegenCommon.callvalueGuard, + Compiler.CodegenCommon.calldatasizeGuard, + List.map_cons, List.map_nil, List.append_nil, + List.cons_append, List.nil_append, List.length_cons, List.length_nil, + if_false, Bool.false_eq_true, + Backends.lowerSwitchCasesNativeWithSwitchIds_cons, + Backends.lowerSwitchCasesNativeWithSwitchIds_nil, + Backends.lowerStmtsNativeWithSwitchIds_cons, + Backends.lowerStmtsNativeWithSwitchIds_nil, + Backends.lowerStmtGroupNativeWithSwitchIds_comment, + Backends.lowerStmtGroupNativeWithSwitchIds_let, + Backends.lowerStmtGroupNativeWithSwitchIds_expr, + Backends.lowerStmtGroupNativeWithSwitchIds_if, + Bind.bind, Except.bind, pure, Except.pure] + +/-- Closed-form selector-miss bridge endpoint for SimpleStorage native +dispatcher. Takes only source-level selector facts (`selector ≠ 0x6057361d` +and `selector ≠ 0x2e64cec1`, the two SimpleStorage IR selectors) and +produces the dispatcher exec result `.error Revert` at fuel `fuel + 21` +(`= fuel + cases'.length + 19` with `cases'.length = 2`). The proof opens the +`_sourceLowered` existential, derives `cases'.find? = none` and `tags-range` +from the source-cases facts via `_find?_none` / `_tags_eq` chained with +`simpleStorageBuildSwitchSourceCases_find?_none` and `_tags_lt_uint256_size`, +then composes through `_selectorMiss_revert_via_reduction`. This lifts the +remaining selector-miss obligation in the SimpleStorage native dispatcher +bridge to a purely source-level statement. -/ +private theorem simpleStorageNativeContract_dispatcherExec_selectorMiss_revert + (fuel selector : Nat) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hSelMissStore : selector ≠ 0x6057361d) + (hSelMissRetrieve : selector ≠ 0x2e64cec1) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + 21) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = + .error EvmYul.Yul.Exception.Revert := by + obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := + simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered + (fuel + 7) tx storage observableSlots hNoWrap + have hLen : cases'.length = 2 := by + have h := Backends.lowerSwitchCasesNativeWithSwitchIds_length_eq + _ _ _ _ _ hLowerCases + rw [h]; rfl + have hFind : cases'.find? (fun entry => entry.1 == selector) = none := + Backends.lowerSwitchCasesNativeWithSwitchIds_find?_none + _ _ _ _ _ _ hLowerCases + (simpleStorageBuildSwitchSourceCases_find?_none hSelMissStore hSelMissRetrieve) + have hTags := Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq + _ _ _ _ _ hLowerCases + have hTagsRange : ∀ tag body, (tag, body) ∈ cases' → + tag < EvmYul.UInt256.size := by + intro tag body hMem + have hMemTag : tag ∈ cases'.map (·.1) := List.mem_map_of_mem hMem + rw [hTags, simpleStorageBuildSwitchSourceCases_map_fst] at hMemTag + simp only [List.mem_cons, List.not_mem_nil, or_false] at hMemTag + rcases hMemTag with rfl | rfl <;> decide + have hReduction := hExec + rw [show (fuel + 7 + 14 : Nat) = fuel + cases'.length + 19 by rw [hLen], + show (fuel + 7 + 8 : Nat) = fuel + cases'.length + 13 by rw [hLen]] + at hReduction + have h := simpleStorageNativeContract_dispatcherExec_selectorMiss_revert_via_reduction + fuel selector (Backends.freshNativeSwitchId reservedNames n0) cases' + tx storage observableSlots hSelector hSelectorRange hFind hTagsRange + hReduction + rw [show fuel + cases'.length + 19 = fuel + 21 by rw [hLen]] at h + exact h + +/-- Post-`__has_selector := 1` switch-prefix state at a hit, with the matched +flag set: the input state shape consumed by the selected body inside the +lowered native switch's hit branch. -/ +private def simpleStorageDispatcherHitBodyInputState + (switchId : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) : EvmYul.Yul.State := + ((((.Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots).sharedState + ((∅ : EvmYul.Yul.VarStore).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) : EvmYul.Yul.State).insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + +/-- Hit-case dual of `_selectorMiss_revert_via_reduction` for the +SimpleStorage `store(uint256)` selector: composes the harness-level +`exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error` +with the strengthened-reduction equation, parametric in `cases'`, the lowered +bodies, and the body-execution `err`. -/ +private theorem simpleStorageNativeContract_dispatcherExec_storeHit_error_via_reduction + (fuel switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) + (hSelector : + 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) + (hCases : cases' = [(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')]) + (hBody : ∀ pre suffix, cases' = pre ++ (0x6057361d, storeBody') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block storeBody') + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState switchId tx storage + observableSlots) = .error err) + (hReduction : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + cases'.length + 19) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' [Backends.Native.nativeRevertZeroZeroStmt]]) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1))) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + cases'.length + 19) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = .error err := by + rw [hReduction] + refine Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error + fuel 0x6057361d switchId 0x6057361d cases' + [Backends.Native.nativeRevertZeroZeroStmt] storeBody' + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots err hSelector ?_ ?_ ?_ ?_ + · rw [hCases]; rfl + · norm_num [EvmYul.UInt256.size] + · intro tag body hMem; rw [hCases] at hMem + simp only [List.mem_cons, Prod.mk.injEq, List.not_mem_nil, or_false] at hMem + rcases hMem with ⟨rfl, _⟩ | ⟨rfl, _⟩ <;> decide + · simpa [simpleStorageDispatcherHitBodyInputState] using hBody + +private def simpleStorageLoweredHitCasesShape + (reservedNames : List String) (n0 midN : Nat) + (storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt) : Prop := + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + simpleStorageBuildSwitchSourceCases = + .ok ([(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')], midN) + +private theorem simpleStorageNativeContract_dispatcherExec_storeHit_error + (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) + (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hBody : ∀ (reservedNames : List String) (n0 midN : Nat) + (storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt), + simpleStorageLoweredHitCasesShape reservedNames n0 midN storeBody' retrieveBody' → + EvmYul.Yul.exec (fuel + 9) (.Block storeBody') + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState + (Backends.freshNativeSwitchId reservedNames n0) tx storage observableSlots) = + .error err) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage observableSlots) = + .error err := by + obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := + simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered + (fuel + 7) tx storage observableSlots hNoWrap + obtain ⟨storeBody', retrieveBody', hCases⟩ := + simpleStorageBuildSwitchSourceCases_lowered_shape reservedNames _ midN cases' hLowerCases + subst hCases + have hBody' := hBody reservedNames n0 midN storeBody' retrieveBody' hLowerCases + have hReduction := hExec + rw [show (fuel + 7 + 14 : Nat) = fuel + 2 + 19 from by omega, + show (fuel + 7 + 8 : Nat) = fuel + 2 + 13 from by omega, + show (2 : Nat) = ([(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] : + List (Nat × List EvmYul.Yul.Ast.Stmt)).length from rfl] at hReduction + have h := simpleStorageNativeContract_dispatcherExec_storeHit_error_via_reduction + fuel (Backends.freshNativeSwitchId reservedNames n0) + [(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] + storeBody' retrieveBody' tx storage observableSlots err + hSelector rfl ?_ hReduction + · rw [show fuel + ([(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] : + List (Nat × List EvmYul.Yul.Ast.Stmt)).length + 19 = fuel + 21 from rfl] at h + exact h + · rintro (_ | ⟨⟨_, _⟩, rest⟩) suffix hDecomp + · simp only [List.nil_append, List.cons.injEq] at hDecomp + obtain ⟨_, hSuf⟩ := hDecomp; subst hSuf; simpa using hBody' + · exfalso + simp only [List.cons_append, List.cons.injEq] at hDecomp + obtain ⟨_, hRest⟩ := hDecomp + cases rest with + | nil => simp only [List.nil_append, List.cons.injEq, Prod.mk.injEq] at hRest + exact absurd hRest.1.1 (by decide) + | cons _ _ => simp at hRest + +private theorem simpleStorageLoweredHitCasesShape_concrete + {reservedNames : List String} {n0 midN : Nat} + {storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt} + (hShape : simpleStorageLoweredHitCasesShape reservedNames n0 midN + storeBody' retrieveBody') : + storeBody' = simpleStorageLoweredStoreCaseBody ∧ + retrieveBody' = simpleStorageLoweredRetrieveCaseBody := by + have hC := simpleStorageBuildSwitchSourceCases_lowered_concrete + reservedNames (Backends.freshNativeSwitchId reservedNames n0 + 1) + unfold simpleStorageLoweredHitCasesShape at hShape + rw [hC] at hShape + simp only [Except.ok.injEq, Prod.mk.injEq, List.cons.injEq] at hShape + exact ⟨hShape.1.1.2.symm, hShape.1.2.1.2.symm⟩ + +/-- Concrete-body variant of `_dispatcherExec_storeHit_error`. The caller now +only has to discharge the body-exec obligation on the *fixed* lowered body +`simpleStorageLoweredStoreCaseBody`, instead of universally over any +`storeBody'` that might come out of the lowering. Uses +`simpleStorageLoweredHitCasesShape_concrete` to specialize the underlying +parametric premise. This strictly weakens the hit-case obligation that the +dispatcher bridge proof has to supply. -/ +private theorem simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete + (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (err : EvmYul.Yul.Exception) + (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hBody : ∀ (reservedNames : List String) (n0 : Nat), + EvmYul.Yul.exec (fuel + 9) (.Block simpleStorageLoweredStoreCaseBody) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState + (Backends.freshNativeSwitchId reservedNames n0) + tx storage observableSlots) = + .error err) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error err := by + refine simpleStorageNativeContract_dispatcherExec_storeHit_error + fuel tx storage observableSlots err hSelector hNoWrap ?_ + intro reservedNames n0 _ storeBody' _ hShape + obtain ⟨hStore, _⟩ := simpleStorageLoweredHitCasesShape_concrete hShape + rw [hStore] + exact hBody reservedNames n0 + +private theorem simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete_tail + (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (err : EvmYul.Yul.Exception) + (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hTail : ∀ (reservedNames : List String) (n0 : Nat), + EvmYul.Yul.exec (fuel + 8) (.Block simpleStorageLoweredStoreCaseBodyTail) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState + (Backends.freshNativeSwitchId reservedNames n0) + tx storage observableSlots) = + .error err) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error err := by + refine simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete + fuel tx storage observableSlots err hSelector hNoWrap ?_ + intro reservedNames n0 + exact exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error + (fuel + 7) _ _ err (hTail reservedNames n0) + +/-- Callvalue-stripped version of `_storeHit_error_concrete_tail`: when the +transaction has zero `msgValue`, the leading `if callvalue() { revert }` guard +is a no-op, so the body-execution premise can be expressed against the +4-statement `simpleStorageLoweredStoreCaseBodyTail2` at fuel `+7` instead of +the 5-statement `simpleStorageLoweredStoreCaseBodyTail` at fuel `+8`. Strictly +shrinks the dispatcher hit-case body-exec obligation under the natural Solidity +assumption that non-payable functions are called with `msg.value = 0`. -/ +private theorem simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete_tail2 + (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (err : EvmYul.Yul.Exception) + (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hMsgValue : tx.msgValue = 0) + (hTail2 : ∀ (reservedNames : List String) (n0 : Nat), + EvmYul.Yul.exec (fuel + 7) + (.Block simpleStorageLoweredStoreCaseBodyTail2) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState + (Backends.freshNativeSwitchId reservedNames n0) + tx storage observableSlots) = + .error err) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error err := by + refine simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete_tail + fuel tx storage observableSlots err hSelector hNoWrap ?_ + intro reservedNames n0 + have hWei : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.weiValue = + (⟨0⟩ : EvmYul.Literal) := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_weiValue, + hMsgValue] + rfl + have hT2 := hTail2 reservedNames n0 + show EvmYul.Yul.exec (fuel + 8) (.Block simpleStorageLoweredStoreCaseBodyTail) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (.Ok _ _) = .error err + exact exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error + fuel _ _ _ err hWei hT2 + +private theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error_via_reduction + (fuel switchId : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) + (hSelector : + 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) + (hCases : cases' = [(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')]) + (hBody : ∀ pre suffix, cases' = pre ++ (0x2e64cec1, retrieveBody') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block retrieveBody') + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState switchId tx storage + observableSlots) = .error err) + (hReduction : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + cases'.length + 19) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block [Backends.lowerNativeSwitchBlock + (Yul.YulExpr.call "shr" [Yul.YulExpr.lit Compiler.Constants.selectorShift, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 0]]) + switchId cases' [Backends.Native.nativeRevertZeroZeroStmt]]) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + ((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1))) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + cases'.length + 19) + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots) = .error err := by + rw [hReduction] + refine Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error + fuel 0x2e64cec1 switchId 0x2e64cec1 cases' + [Backends.Native.nativeRevertZeroZeroStmt] retrieveBody' + Compiler.SimpleStorageNativeWitness.nativeContract + tx storage observableSlots err hSelector ?_ ?_ ?_ ?_ + · rw [hCases]; rfl + · norm_num [EvmYul.UInt256.size] + · intro tag body hMem; rw [hCases] at hMem + simp only [List.mem_cons, Prod.mk.injEq, List.not_mem_nil, or_false] at hMem + rcases hMem with ⟨rfl, _⟩ | ⟨rfl, _⟩ <;> decide + · simpa [simpleStorageDispatcherHitBodyInputState] using hBody + +private theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error + (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) + (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hBody : ∀ (reservedNames : List String) (n0 midN : Nat) + (storeBody' retrieveBody' : List EvmYul.Yul.Ast.Stmt), + simpleStorageLoweredHitCasesShape reservedNames n0 midN storeBody' retrieveBody' → + EvmYul.Yul.exec (fuel + 8) (.Block retrieveBody') + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState + (Backends.freshNativeSwitchId reservedNames n0) tx storage observableSlots) = + .error err) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage observableSlots) = + .error err := by + obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := + simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered + (fuel + 7) tx storage observableSlots hNoWrap + obtain ⟨storeBody', retrieveBody', hCases⟩ := + simpleStorageBuildSwitchSourceCases_lowered_shape reservedNames _ midN cases' hLowerCases + subst hCases + have hBody' := hBody reservedNames n0 midN storeBody' retrieveBody' hLowerCases + have hReduction := hExec + rw [show (fuel + 7 + 14 : Nat) = fuel + 2 + 19 from by omega, + show (fuel + 7 + 8 : Nat) = fuel + 2 + 13 from by omega, + show (2 : Nat) = ([(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] : + List (Nat × List EvmYul.Yul.Ast.Stmt)).length from rfl] at hReduction + have h := simpleStorageNativeContract_dispatcherExec_retrieveHit_error_via_reduction + fuel (Backends.freshNativeSwitchId reservedNames n0) + [(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] + storeBody' retrieveBody' tx storage observableSlots err + hSelector rfl ?_ hReduction + · rw [show fuel + ([(0x6057361d, storeBody'), (0x2e64cec1, retrieveBody')] : + List (Nat × List EvmYul.Yul.Ast.Stmt)).length + 19 = fuel + 21 from rfl] at h + exact h + · rintro (_ | ⟨⟨_, _⟩, rest⟩) suffix hDecomp + · exfalso + simp only [List.nil_append, List.cons.injEq, Prod.mk.injEq] at hDecomp + exact absurd hDecomp.1.1 (by decide) + · simp only [List.cons_append, List.cons.injEq] at hDecomp + obtain ⟨_, hRest⟩ := hDecomp + cases rest with + | nil => simp only [List.nil_append, List.cons.injEq] at hRest + obtain ⟨_, hSuf⟩ := hRest; subst hSuf; simpa using hBody' + | cons _ _ => simp at hRest + +private theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete + (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (err : EvmYul.Yul.Exception) + (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hBody : ∀ (reservedNames : List String) (n0 : Nat), + EvmYul.Yul.exec (fuel + 8) (.Block simpleStorageLoweredRetrieveCaseBody) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState + (Backends.freshNativeSwitchId reservedNames n0) + tx storage observableSlots) = + .error err) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error err := by + refine simpleStorageNativeContract_dispatcherExec_retrieveHit_error + fuel tx storage observableSlots err hSelector hNoWrap ?_ + intro reservedNames n0 _ _ retrieveBody' hShape + obtain ⟨_, hRetrieve⟩ := simpleStorageLoweredHitCasesShape_concrete hShape + rw [hRetrieve] + exact hBody reservedNames n0 + +private theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail + (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (err : EvmYul.Yul.Exception) + (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hTail : ∀ (reservedNames : List String) (n0 : Nat), + EvmYul.Yul.exec (fuel + 7) (.Block simpleStorageLoweredRetrieveCaseBodyTail) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState + (Backends.freshNativeSwitchId reservedNames n0) + tx storage observableSlots) = + .error err) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error err := by + refine simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete + fuel tx storage observableSlots err hSelector hNoWrap ?_ + intro reservedNames n0 + exact exec_block_simpleStorageLoweredRetrieveCaseBody_head_strip_error + (fuel + 6) _ _ err (hTail reservedNames n0) + +/-- Retrieve-case dual of `_storeHit_error_concrete_tail2`. -/ +private theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail2 + (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (err : EvmYul.Yul.Exception) + (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hMsgValue : tx.msgValue % EvmYul.UInt256.size = 0) + (hTail2 : ∀ (reservedNames : List String) (n0 : Nat), + EvmYul.Yul.exec (fuel + 6) + (.Block simpleStorageLoweredRetrieveCaseBodyTail2) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState + (Backends.freshNativeSwitchId reservedNames n0) + tx storage observableSlots) = + .error err) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + 21) Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error err := by + refine simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail + fuel tx storage observableSlots err hSelector hNoWrap ?_ + intro reservedNames n0 + have hWei : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.weiValue = + (⟨0⟩ : EvmYul.Literal) := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_weiValue] + apply congrArg EvmYul.UInt256.mk + apply Fin.ext + simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256, + EvmYul.UInt256.ofNat, Fin.ofNat] using hMsgValue + have hT2 := hTail2 reservedNames n0 + show EvmYul.Yul.exec (fuel + 7) (.Block simpleStorageLoweredRetrieveCaseBodyTail) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (.Ok _ _) = .error err + exact exec_block_simpleStorageLoweredRetrieveCaseBodyTail_callvalue_strip_error + fuel _ _ _ err hWei hT2 + +/-- Retrieve-case wrapper that further shrinks the body-exec obligation by +also stripping the inner `if lt(calldatasize(), 4) {…}` argument-length revert +guard. The user supplies the tail3 obligation (the 2-statement +`mstore(0, sload(0)); return(0, 32)` core) and the wrapper discharges both +the callvalue and lt-calldatasize guards via the strip lemmas. The +calldata-size assumptions are derived automatically from `hNoWrap` and +`initialState_calldataSize`. -/ +private theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail3 + (fuel : Nat) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (err : EvmYul.Yul.Exception) + (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hMsgValue : tx.msgValue % EvmYul.UInt256.size = 0) + (hTail3 : ∀ (reservedNames : List String) (n0 : Nat), + EvmYul.Yul.exec (fuel + 9) + (.Block simpleStorageLoweredRetrieveCaseBodyTail3) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState + (Backends.freshNativeSwitchId reservedNames n0) + tx storage observableSlots) = + .error err) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + (fuel + 25) Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error err := by + refine simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail2 + (fuel + 4) tx storage observableSlots err hSelector hNoWrap hMsgValue ?_ + intro reservedNames n0 + have hT3 := hTail3 reservedNames n0 + have hSize : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.calldata.size < + EvmYul.UInt256.size := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] + exact hNoWrap + have hGe : + 4 ≤ (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.calldata.size := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] + exact Nat.le_add_right 4 _ + show EvmYul.Yul.exec ((fuel + 4) + 6) + (.Block simpleStorageLoweredRetrieveCaseBodyTail2) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (.Ok _ _) = .error err + exact exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error + fuel _ _ _ err hSize hGe hT3 + +private noncomputable def simpleStorageNativeDispatcherFuel : Nat := + sizeOf [Compiler.CodegenCommon.buildSwitch + simpleStorageIRContract.functions none none] + +/-- Lower bound on the SimpleStorage native dispatcher fuel constant for +the retrieve-hit and store-hit bridges, which use the `_concrete_tail3` +chain that produces dispatcher exec at `fuel + 25`. -/ +private theorem simpleStorageNativeDispatcherFuel_ge_25 : + simpleStorageNativeDispatcherFuel ≥ 25 := by + unfold simpleStorageNativeDispatcherFuel + decide + +private theorem simpleStorageNativeDispatcherFuel_ge_21 : + simpleStorageNativeDispatcherFuel ≥ 21 := by + exact Nat.le_trans (by decide) simpleStorageNativeDispatcherFuel_ge_25 + +/-- Native dispatcher exec at exactly `simpleStorageNativeDispatcherFuel` +reduces to `.error Revert` for the selector-miss class. -/ +private theorem simpleStorageNativeContract_dispatcherExec_selectorMiss_revert_atFuel + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (hSelectorRange : tx.functionSelector % Compiler.Constants.selectorModulus + < EvmYul.UInt256.size) + (hSelMissStore : tx.functionSelector % Compiler.Constants.selectorModulus + ≠ 0x6057361d) + (hSelMissRetrieve : tx.functionSelector % Compiler.Constants.selectorModulus + ≠ 0x2e64cec1) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + simpleStorageNativeDispatcherFuel + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert := by + have hReshape : simpleStorageNativeDispatcherFuel = + (simpleStorageNativeDispatcherFuel - 21) + 21 := + (Nat.sub_add_cancel simpleStorageNativeDispatcherFuel_ge_21).symm + rw [hReshape] + exact simpleStorageNativeContract_dispatcherExec_selectorMiss_revert + (simpleStorageNativeDispatcherFuel - 21) + (tx.functionSelector % Compiler.Constants.selectorModulus) + tx storage observableSlots + rfl hSelectorRange hSelMissStore hSelMissRetrieve hNoWrap + +/-- Closed-form `interpretIR` reduction for the SimpleStorage selector-miss +class. Given the two raw selector mismatches (`≠ 0x6057361d` and +`≠ 0x2e64cec1`), `interpretIR` falls into the `find?`-`none` branch and returns +the trivial reverted shape with storage and events untouched. -/ +private theorem interpretIR_simpleStorage_selectorMiss + (tx : IRTransaction) (initialState : IRState) + (hSelMissStore : tx.functionSelector ≠ 0x6057361d) + (hSelMissRetrieve : tx.functionSelector ≠ 0x2e64cec1) : + interpretIR simpleStorageIRContract tx initialState = + { success := false + returnValue := none + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + unfold interpretIR + simp only [simpleStorageIRContract, List.find?] + have hstore : (0x6057361d == tx.functionSelector) = false := by + simp [BEq.beq, hSelMissStore.symm] + have hretrieve : (0x2e64cec1 == tx.functionSelector) = false := by + simp [BEq.beq, hSelMissRetrieve.symm] + simp [hstore, hretrieve] + +/-- Closed-form `interpretIR` reduction for the SimpleStorage retrieve-hit +class. Given the raw selector match (`= 0x2e64cec1`), `interpretIR` enters the +`retrieve` body which is read-only on storage: it loads slot 0 via `sload`, +mirrors it into memory[0..32] via `mstore`, and returns those 32 bytes. The +returned word equals `(state.storage (IRStorageSlot.ofNat 0)).toNat` (where `state` is +`initialState.withTx tx`). Storage and events are unchanged. + + After Phase 1 of the IR storage refactor, + `state.storage (IRStorageSlot.ofNat 0) : IRStorageWord` is `UInt256`-bounded, + so `(state.storage (IRStorageSlot.ofNat 0)).toNat < 2^256`. This is the +IR-side input to the direct native retrieve-hit match proof. -/ +private theorem interpretIR_simpleStorage_retrieveHit + (tx : IRTransaction) (initialState : IRState) + (hSel : tx.functionSelector = 0x2e64cec1) + (hMsgValue : tx.msgValue % evmModulus = 0) : + interpretIR simpleStorageIRContract tx initialState = + { success := true + returnValue := some ((initialState.storage (IRStorageSlot.ofNat 0)).toNat) + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + have hstore : (0x6057361d == tx.functionSelector) = false := by + simp [BEq.beq, hSel] + have hretrieve : (0x2e64cec1 == tx.functionSelector) = true := by + simp [BEq.beq, hSel] + -- Closed-form evaluation of the retrieve body for any fuel ≥ 2. + have hbody : ∀ (n : Nat) (s : IRState), 2 ≤ n → + execIRStmts (n + 1) s + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] = + .return ((s.storage (IRStorageSlot.ofNat 0)).toNat) + { s with memory := fun o => + if o = 0 then (s.storage (IRStorageSlot.ofNat 0)).toNat else s.memory o } := by + intro n s hn + obtain ⟨k, rfl⟩ : ∃ k, n = k + 2 := ⟨n - 2, by omega⟩ + -- Fuel `k + 2 + 1 = k + 3` is `Nat.succ (Nat.succ (Nat.succ k))`, allowing + -- both the outer `execIRStmts` and the inner `execIRStmt` to step. + simp +decide only [execIRStmts, execIRStmt, evalIRExpr, evalIRCall_sload_singleton, + Compiler.Proofs.abstractLoadStorageOrMapping, + Option.bind_some, ↓reduceIte] + -- The retrieve body has at least 2 statements, so `sizeOf body ≥ 2` by + -- direct computation on the auto-derived size measure. + have hsize : 2 ≤ sizeOf + ([Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] : List Yul.YulStmt) := by + decide + unfold interpretIR + simp only [simpleStorageIRContract, List.find?, hstore, hretrieve, + List.length_nil, Nat.zero_le, ↓reduceDIte] + -- Now goal involves `execIRFunction retrieveFn tx.args state'`. + unfold execIRFunction + simp only [List.zip_nil_left, List.foldl_nil] + -- Goal: `match execIRStmts (sizeOf body + 1) state' body with ... = ...`. + rw [hbody _ _ hsize] + simp [hMsgValue] + +/-- Closed-form `interpretIR` reduction for the SimpleStorage store-hit class +when the ABI argument is present. The IR setter writes the first calldata word +to bounded storage slot zero and stops successfully. -/ +private theorem interpretIR_simpleStorage_storeHit_arg + (tx : IRTransaction) (initialState : IRState) + (arg : Nat) (rest : List Nat) + (hSel : tx.functionSelector = 0x6057361d) + (hArgs : tx.args = arg :: rest) + (hMsgValue : tx.msgValue % evmModulus = 0) : + interpretIR simpleStorageIRContract tx initialState = + { success := true + returnValue := none + finalStorage := + Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 + (arg % evmModulus) + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 + (arg % evmModulus)) + events := initialState.events } := by + have hstore : (0x6057361d == tx.functionSelector) = true := by + simp [BEq.beq, hSel] + let storeFn : IRFunction := + { name := "store" + selector := 0x6057361d + params := [{ name := "value", ty := IRType.uint256 }] + ret := IRType.unit + body := [ + Yul.YulStmt.let_ "value" (Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]), + Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])] } + have hExec := + Compiler.Proofs.IRGeneration.execIRFunction_store0_calldataload4_stop_of_args_cons + storeFn tx initialState arg rest (by rfl) hArgs + unfold interpretIR + simp only [simpleStorageIRContract, List.find?, hstore, List.length_cons, + List.length_nil, Nat.reduceAdd] + simpa [storeFn, applyIRTransactionContext, hArgs, hMsgValue, evmModulus] using hExec + +/-- Closed-form `interpretIR` reduction for the SimpleStorage store-hit class +when calldata is too short for the single setter argument. The dispatcher +selects the function, but the IR arity guard fails before executing the body. -/ +private theorem interpretIR_simpleStorage_storeHit_short + (tx : IRTransaction) (initialState : IRState) + (hSel : tx.functionSelector = 0x6057361d) + (hShort : tx.args = []) : + interpretIR simpleStorageIRContract tx initialState = + { success := false + returnValue := none + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + have hstore : (0x6057361d == tx.functionSelector) = true := by + simp [BEq.beq, hSel] + unfold interpretIR + simp [simpleStorageIRContract, hstore, hShort] + +/-- Native dispatcher exec at exactly `simpleStorageNativeDispatcherFuel` +reduces to `.error (YulHalt (.Ok shared3 _) ⟨1⟩)` for the retrieve-hit class, +where `shared3` is the closed-form shared state after the +`mstore(0, sload(0))` and `return(0, 32)` updates. The Yul varStore inside +the halt state depends on the fresh switch identifier (which the dispatcher +chose internally), so it is left existentially quantified — `projectResult` +on `.error (YulHalt _ _)` ignores the varStore, so this is sufficient for +the bridge proof. Composes the body-level closed form +`exec_block_simpleStorageLoweredRetrieveCaseBody_halt` with +`_retrieveHit_error_via_reduction` after opening the `_sourceLowered` +existential and pinning `cases'` via `_lowered_shape` and +`_lowered_concrete`. The `_concrete_tail*` chain is bypassed because it +universally quantifies over `(reservedNames, n0)` against a single fixed +`err`, which is incompatible with the switchId-dependent varStore inside +the halt-error term. -/ +private theorem simpleStorageNativeContract_dispatcherExec_retrieveHit_halt_atFuel + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hMsgValue : tx.msgValue % EvmYul.UInt256.size = 0) : + let shared := (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState + let p := shared.sload (EvmYul.UInt256.ofNat 0) + let shared1 : EvmYul.SharedState .Yul := { shared with toState := p.1 } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) p.2 } + let shared3 : EvmYul.SharedState .Yul := + { shared2 with + toMachineState := + shared2.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + ∃ store : EvmYul.Yul.VarStore, + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + simpleStorageNativeDispatcherFuel + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store) ⟨1⟩) := by + -- Bring the let-bound names from the goal into the local context. + intro shared p shared1 shared2 shared3 + -- Reshape dispatcher fuel to `g + 25` where `g := dispatcherFuel - 25`. + set g := simpleStorageNativeDispatcherFuel - 25 with hg_def + have hReshape : simpleStorageNativeDispatcherFuel = g + 25 := + (Nat.sub_add_cancel simpleStorageNativeDispatcherFuel_ge_25).symm + rw [hReshape] + -- Open the `_sourceLowered` existential at `peeledFuel := g + 11`, so the + -- dispatcher LHS lands at `(g + 11) + 14 = g + 25`. + obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := + simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered + (g + 11) tx storage observableSlots hNoWrap + -- Pin `cases'` to the two-element shape. + obtain ⟨storeBody', retrieveBody', hCases⟩ := + simpleStorageBuildSwitchSourceCases_lowered_shape reservedNames _ midN + cases' hLowerCases + subst hCases + -- Pin the lowered bodies to the concrete forms. + obtain ⟨hStoreBody, hRetrieveBody⟩ := + simpleStorageLoweredHitCasesShape_concrete hLowerCases + subst hStoreBody + subst hRetrieveBody + -- The chained-insert varStore for the dispatcher hit-body input state. + set switchId := Backends.freshNativeSwitchId reservedNames n0 with hSw + let store_body : EvmYul.Yul.VarStore := + ((((∅ : EvmYul.Yul.VarStore).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)).insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) + -- Provide `store := store_body` for the existential. + refine ⟨store_body, ?_⟩ + -- Discharge the body-level closed form via `_RetrieveCaseBody_halt`. + have hWei : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.weiValue = + (⟨0⟩ : EvmYul.Literal) := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_weiValue] + apply congrArg EvmYul.UInt256.mk + apply Fin.ext + simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256, + EvmYul.UInt256.ofNat, Fin.ofNat] using hMsgValue + have hSize : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.calldata.size < + EvmYul.UInt256.size := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] + exact hNoWrap + have hGe : + 4 ≤ (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.calldata.size := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] + exact Nat.le_add_right 4 _ + have hBodyHalt := + exec_block_simpleStorageLoweredRetrieveCaseBody_halt g + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState + store_body hWei hSize hGe + -- Reshape `hExec` into the form expected by `_via_reduction`'s + -- `hReduction` parameter. + have hReduction := hExec + rw [show (g + 11 + 14 : Nat) = (g + 4) + 2 + 19 from by omega, + show (g + 11 + 8 : Nat) = (g + 4) + 2 + 13 from by omega, + show (2 : Nat) = ([(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : + List (Nat × List EvmYul.Yul.Ast.Stmt)).length from rfl] at hReduction + -- Body-execution premise of `_via_reduction`: only valid decomposition is + -- `pre = [(0x6057361d, store)]`, `suffix = []`. Body fuel is + -- `(g + 4 + 1) + 0 + 7 = g + 12`, matching `hBodyHalt`. + have hBodyExec : ∀ pre suffix, + ([(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : + List (Nat × List EvmYul.Yul.Ast.Stmt)) = + pre ++ (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody) :: suffix → + EvmYul.Yul.exec (((g + 4) + 1) + suffix.length + 7) + (.Block simpleStorageLoweredRetrieveCaseBody) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState switchId tx storage + observableSlots) = + .error (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store_body) ⟨1⟩) := by + rintro pre suffix hDecomp + cases pre with + | nil => + simp only [List.nil_append, List.cons.injEq, Prod.mk.injEq] at hDecomp + exfalso + exact absurd hDecomp.1.1 (by decide) + | cons _ rest => + simp only [List.cons_append, List.cons.injEq] at hDecomp + obtain ⟨_, hRest⟩ := hDecomp + cases rest with + | nil => + simp only [List.nil_append, List.cons.injEq] at hRest + obtain ⟨_, hSuf⟩ := hRest + subst hSuf + simpa [simpleStorageDispatcherHitBodyInputState] using hBodyHalt + | cons _ _ => simp at hRest + -- Apply `_retrieveHit_error_via_reduction` at `fuel := g + 4` with + -- `err := YulHalt (.Ok shared3 store_body) ⟨1⟩`. + have h := simpleStorageNativeContract_dispatcherExec_retrieveHit_error_via_reduction + (g + 4) switchId + [(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] + simpleStorageLoweredStoreCaseBody simpleStorageLoweredRetrieveCaseBody + tx storage observableSlots + (EvmYul.Yul.Exception.YulHalt (.Ok shared3 store_body) ⟨1⟩) + hSelector rfl hBodyExec hReduction + -- `h` has dispatcher fuel `(g + 4) + cases'.length + 19`. Reshape to `g + 25`. + have hLen : + ([(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : + List (Nat × List EvmYul.Yul.Ast.Stmt)).length = 2 := rfl + rw [hLen, show (g + 4) + 2 + 19 = g + 25 from by omega] at h + exact h + +/-- Native dispatcher exec at exactly `simpleStorageNativeDispatcherFuel` reduces to the `STOP` halt for the store-hit class when calldata supplies the setter argument. -/ -theorem simpleStorageNativeContract_dispatcherExec_storeHit_halt_atFuel +private theorem simpleStorageNativeContract_dispatcherExec_storeHit_halt_atFuel + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (arg : Nat) (rest : List Nat) (hArgs : tx.args = arg :: rest) + (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hMsgValue : tx.msgValue % EvmYul.UInt256.size = 0) : + ∃ store_body haltState, + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + simpleStorageNativeDispatcherFuel + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error (EvmYul.Yul.Exception.YulHalt haltState ⟨0⟩) ∧ + haltState = + let initialWithStore : EvmYul.Yul.State := + .Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState store_body + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) := by + set g := simpleStorageNativeDispatcherFuel - 25 with hg_def + have hReshape : simpleStorageNativeDispatcherFuel = g + 25 := + (Nat.sub_add_cancel simpleStorageNativeDispatcherFuel_ge_25).symm + rw [hReshape] + obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := + simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered + (g + 11) tx storage observableSlots hNoWrap + obtain ⟨storeBody', retrieveBody', hCases⟩ := + simpleStorageBuildSwitchSourceCases_lowered_shape reservedNames _ midN + cases' hLowerCases + subst hCases + obtain ⟨hStoreBody, hRetrieveBody⟩ := + simpleStorageLoweredHitCasesShape_concrete hLowerCases + subst hStoreBody + subst hRetrieveBody + set switchId := Backends.freshNativeSwitchId reservedNames n0 with hSw + let store_body : EvmYul.Yul.VarStore := + ((((∅ : EvmYul.Yul.VarStore).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)).insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) + let initialWithStore : EvmYul.Yul.State := + .Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState store_body + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let finalState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + refine ⟨store_body, finalState, ?_, ?_⟩ + · have hWei : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.weiValue = + (⟨0⟩ : EvmYul.Literal) := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_weiValue] + apply congrArg EvmYul.UInt256.mk + apply Fin.ext + simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256, + EvmYul.UInt256.ofNat, Fin.ofNat] using hMsgValue + have hSize : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.calldata.size < + EvmYul.UInt256.size := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] + exact hNoWrap + have hGe : + 36 ≤ (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.calldata.size := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] + rw [hArgs] + simp + omega + have hBodyHalt := + exec_block_simpleStorageLoweredStoreCaseBody_halt g + (some Compiler.SimpleStorageNativeWitness.nativeContract) + tx storage observableSlots store_body arg rest hArgs hWei hSize hGe + have hReduction := hExec + rw [show (g + 11 + 14 : Nat) = (g + 4) + 2 + 19 from by omega, + show (g + 11 + 8 : Nat) = (g + 4) + 2 + 13 from by omega, + show (2 : Nat) = ([(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : + List (Nat × List EvmYul.Yul.Ast.Stmt)).length from rfl] at hReduction + have hBodyExec : ∀ pre suffix, + ([(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : + List (Nat × List EvmYul.Yul.Ast.Stmt)) = + pre ++ (0x6057361d, simpleStorageLoweredStoreCaseBody) :: suffix → + EvmYul.Yul.exec (((g + 4) + 1) + suffix.length + 7) + (.Block simpleStorageLoweredStoreCaseBody) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState switchId tx storage + observableSlots) = + .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by + rintro pre suffix hDecomp + cases pre with + | nil => + simp only [List.nil_append, List.cons.injEq] at hDecomp + obtain ⟨_, hSuf⟩ := hDecomp + subst hSuf + simpa [simpleStorageDispatcherHitBodyInputState, initialWithStore, + withValue, finalState] using hBodyHalt + | cons _ restPre => + exfalso + simp only [List.cons_append, List.cons.injEq] at hDecomp + obtain ⟨_, hRest⟩ := hDecomp + cases restPre with + | nil => + simp only [List.nil_append, List.cons.injEq, Prod.mk.injEq] at hRest + exact absurd hRest.1.1 (by decide) + | cons _ _ => simp at hRest + have h := simpleStorageNativeContract_dispatcherExec_storeHit_error_via_reduction + (g + 4) switchId + [(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] + simpleStorageLoweredStoreCaseBody simpleStorageLoweredRetrieveCaseBody + tx storage observableSlots + (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) + hSelector rfl hBodyExec hReduction + have hLen : + ([(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : + List (Nat × List EvmYul.Yul.Ast.Stmt)).length = 2 := rfl + rw [hLen, show (g + 4) + 2 + 19 = g + 25 from by omega] at h + exact h + · rfl + +/-- Native dispatcher exec at exactly `simpleStorageNativeDispatcherFuel` +reverts for the store-hit class when calldata contains no setter argument. -/ +private theorem simpleStorageNativeContract_dispatcherExec_storeHit_short_revert_atFuel (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (arg : Nat) (rest : List Nat) (hArgs : tx.args = arg :: rest) + (hArgs : tx.args = []) (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hMsgValue : tx.msgValue % EvmYul.UInt256.size = 0) : - ∃ store_body haltState, - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - simpleStorageNativeDispatcherFuel - Compiler.SimpleStorageNativeWitness.nativeContract + (hMsgValue : tx.msgValue % EvmYul.UInt256.size = 0) : + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult + simpleStorageNativeDispatcherFuel + Compiler.SimpleStorageNativeWitness.nativeContract + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert := by + set g := simpleStorageNativeDispatcherFuel - 25 with hg_def + have hReshape : simpleStorageNativeDispatcherFuel = g + 25 := + (Nat.sub_add_cancel simpleStorageNativeDispatcherFuel_ge_25).symm + rw [hReshape] + obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := + simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered + (g + 11) tx storage observableSlots hNoWrap + obtain ⟨storeBody', retrieveBody', hCases⟩ := + simpleStorageBuildSwitchSourceCases_lowered_shape reservedNames _ midN + cases' hLowerCases + subst hCases + obtain ⟨hStoreBody, hRetrieveBody⟩ := + simpleStorageLoweredHitCasesShape_concrete hLowerCases + subst hStoreBody + subst hRetrieveBody + set switchId := Backends.freshNativeSwitchId reservedNames n0 with hSw + let store_body : EvmYul.Yul.VarStore := + ((((∅ : EvmYul.Yul.VarStore).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)).insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) + have hWei : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.weiValue = + (⟨0⟩ : EvmYul.Literal) := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_weiValue] + apply congrArg EvmYul.UInt256.mk + apply Fin.ext + simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256, + EvmYul.UInt256.ofNat, Fin.ofNat] using hMsgValue + have hSizeEq : + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState.executionEnv.calldata.size = 4 := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] + simp [hArgs] + have hTail2 := + exec_block_simpleStorageLoweredStoreCaseBodyTail2_short_revert + g (some Compiler.SimpleStorageNativeWitness.nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState + store_body hSizeEq + have hTail := + exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error + (g + 4) (some Compiler.SimpleStorageNativeWitness.nativeContract) + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + Compiler.SimpleStorageNativeWitness.nativeContract tx storage + observableSlots).sharedState + store_body _ hWei hTail2 + have hBodyRevert : + EvmYul.Yul.exec (g + 13) (.Block simpleStorageLoweredStoreCaseBody) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState switchId tx storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert := by + exact exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error + (g + 11) _ _ _ hTail + have hReduction := hExec + rw [show (g + 11 + 14 : Nat) = (g + 4) + 2 + 19 from by omega, + show (g + 11 + 8 : Nat) = (g + 4) + 2 + 13 from by omega, + show (2 : Nat) = ([(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : + List (Nat × List EvmYul.Yul.Ast.Stmt)).length from rfl] at hReduction + have hBodyExec : ∀ pre suffix, + ([(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : + List (Nat × List EvmYul.Yul.Ast.Stmt)) = + pre ++ (0x6057361d, simpleStorageLoweredStoreCaseBody) :: suffix → + EvmYul.Yul.exec (((g + 4) + 1) + suffix.length + 7) + (.Block simpleStorageLoweredStoreCaseBody) + (some Compiler.SimpleStorageNativeWitness.nativeContract) + (simpleStorageDispatcherHitBodyInputState switchId tx storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert := by + rintro pre suffix hDecomp + cases pre with + | nil => + simp only [List.nil_append, List.cons.injEq] at hDecomp + obtain ⟨_, hSuf⟩ := hDecomp + subst hSuf + simpa [simpleStorageDispatcherHitBodyInputState, store_body] using hBodyRevert + | cons _ restPre => + exfalso + simp only [List.cons_append, List.cons.injEq] at hDecomp + obtain ⟨_, hRest⟩ := hDecomp + cases restPre with + | nil => + simp only [List.nil_append, List.cons.injEq, Prod.mk.injEq] at hRest + exact absurd hRest.1.1 (by decide) + | cons _ _ => simp at hRest + have h := simpleStorageNativeContract_dispatcherExec_storeHit_error_via_reduction + (g + 4) switchId + [(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] + simpleStorageLoweredStoreCaseBody simpleStorageLoweredRetrieveCaseBody + tx storage observableSlots EvmYul.Yul.Exception.Revert + hSelector rfl hBodyExec hReduction + have hLen : + ([(0x6057361d, simpleStorageLoweredStoreCaseBody), + (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : + List (Nat × List EvmYul.Yul.Ast.Stmt)).length = 2 := rfl + rw [hLen, show (g + 4) + 2 + 19 = g + 25 from by omega] at h + exact h + +/-- Projected native storage after the generated `store(uint256)` body agrees +with the IR setter update on every materialized slot. The native zero-write +case erases slot zero from the finite EVM map; projected lookup still agrees +with IR storage because missing native storage reads as the zero word. -/ +private theorem projectStorageFromState_storeHit_initialState_materialized + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (slots : List Nat) (store : EvmYul.Yul.VarStore) + (arg slot : Nat) + (hSlot : slot ∈ slots) : + let initialWithStore : EvmYul.Yul.State := + .Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState + contract tx storage slots).sharedState store + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let finalState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState tx + finalState (IRStorageSlot.ofNat slot) = + (Compiler.Proofs.abstractStoreStorageOrMapping storage 0 arg) + (IRStorageSlot.ofNat slot) := by + intro initialWithStore withValue finalState + simp only [Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.extractStorage, + finalState, withValue, initialWithStore, + EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.Yul.State.insert, + EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, + Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256] + simp only [Option.option, + Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + by_cases hValueZero : + (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = true + · rw [hValueZero] + simp only [ite_true, IRStorageSlot.toUInt256, IRStorageSlot.ofNat] + have hArgZeroUInt : + EvmYul.UInt256.ofNat arg = (⟨0⟩ : EvmYul.UInt256) := by + cases hArg : EvmYul.UInt256.ofNat arg with + | mk v => + rw [hArg] at hValueZero + change (v == (0 : Fin EvmYul.UInt256.size)) = true at hValueZero + have hv : v = (0 : Fin EvmYul.UInt256.size) := + of_decide_eq_true hValueZero + subst hv + rfl + have hArgZero : IRStorageWord.ofNat arg = (0 : IRStorageWord) := by + simpa [Compiler.Proofs.IRGeneration.IRStorageWord.ofNat] using hArgZeroUInt + by_cases hKey : + compare (EvmYul.UInt256.ofNat slot) (EvmYul.UInt256.ofNat 0) = + Ordering.eq + · have hSlotEq : + IRStorageSlot.ofNat slot = IRStorageSlot.ofNat 0 := by + have hUInt : + EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := + Compiler.Proofs.YulGeneration.Backends.StateBridge.UInt256_eq_of_compare_eq + hKey + simpa [IRStorageSlot.ofNat] using hUInt + have hUInt : + EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := by + simpa [IRStorageSlot.ofNat] using hSlotEq + have hErase : + (Batteries.RBMap.erase + (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage + storage slots) + (EvmYul.UInt256.ofNat 0)).find? (EvmYul.UInt256.ofNat slot) = + none := by + simpa [hUInt] using + (Batteries.RBMap.find?_erase_self + (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage + storage slots) + (EvmYul.UInt256.ofNat 0)) + rw [hErase, hUInt] + simp only [Compiler.Proofs.abstractStoreStorageOrMapping, + Compiler.Proofs.IRGeneration.IRStorageWord.ofNat, IRStorageSlot.ofNat] + simp only [if_true] + rw [hArgZeroUInt] + rfl + · have hErase : + (Batteries.RBMap.erase + (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage + storage slots) + (EvmYul.UInt256.ofNat 0)).find? (EvmYul.UInt256.ofNat slot) = + (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage + storage slots).find? (EvmYul.UInt256.ofNat slot) := by + exact Batteries.RBMap.find?_erase_of_ne _ hKey + have hLookup := + Compiler.Proofs.YulGeneration.Backends.StateBridge.storageLookup_projectStorage_projected + storage slots slot hSlot + have hLookup' : + (match + (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage + storage slots).find? (EvmYul.UInt256.ofNat slot) with + | some val => val + | none => (⟨0⟩ : EvmYul.UInt256)) = + storage (IRStorageSlot.ofNat slot) := by + simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.storageLookup, + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256] + using hLookup + rw [hErase] + have hSlotNe : + IRStorageSlot.ofNat slot ≠ IRStorageSlot.ofNat 0 := by + intro hEq + apply hKey + have hUIntEq : + EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := by + simpa [IRStorageSlot.ofNat] using hEq + rw [hUIntEq] + exact Std.ReflCmp.compare_self + have hSlotNe' : + EvmYul.UInt256.ofNat slot ≠ IRStorageSlot.ofNat 0 := by + simpa [IRStorageSlot.ofNat] using hSlotNe + have hSlotNeUInt : + EvmYul.UInt256.ofNat slot ≠ EvmYul.UInt256.ofNat 0 := by + intro hEq + exact hSlotNe' (by simpa [IRStorageSlot.ofNat] using hEq) + simpa [Compiler.Proofs.abstractStoreStorageOrMapping, IRStorageSlot.ofNat, + hSlotNeUInt] using hLookup' + · have hValueNonzero : + (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = + false := by + cases h : + (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) <;> + simp [h] at hValueZero ⊢ + rw [hValueNonzero] + simp only [Bool.false_eq_true, ite_false, IRStorageSlot.toUInt256, + IRStorageSlot.ofNat] + by_cases hKey : + compare (EvmYul.UInt256.ofNat slot) (EvmYul.UInt256.ofNat 0) = + Ordering.eq + · have hSlotEq : + IRStorageSlot.ofNat slot = IRStorageSlot.ofNat 0 := by + have hUInt : + EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := + Compiler.Proofs.YulGeneration.Backends.StateBridge.UInt256_eq_of_compare_eq + hKey + simpa [IRStorageSlot.ofNat] using hUInt + have hUInt : + EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := by + simpa [IRStorageSlot.ofNat] using hSlotEq + rw [Batteries.RBMap.find?_insert_of_eq _ hKey] + rw [hUInt] + simp [Compiler.Proofs.abstractStoreStorageOrMapping, + Compiler.Proofs.IRGeneration.IRStorageWord.ofNat, IRStorageSlot.ofNat] + · rw [Batteries.RBMap.find?_insert_of_ne _ hKey] + have hLookup := + Compiler.Proofs.YulGeneration.Backends.StateBridge.storageLookup_projectStorage_projected + storage slots slot hSlot + have hLookup' : + (match + (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage + storage slots).find? (EvmYul.UInt256.ofNat slot) with + | some val => val + | none => (⟨0⟩ : EvmYul.UInt256)) = + storage (IRStorageSlot.ofNat slot) := by + simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.storageLookup, + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256] + using hLookup + have hSlotNe : + IRStorageSlot.ofNat slot ≠ IRStorageSlot.ofNat 0 := by + intro hEq + apply hKey + have hUIntEq : + EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := by + simpa [IRStorageSlot.ofNat] using hEq + rw [hUIntEq] + exact Std.ReflCmp.compare_self + have hSlotNe' : + EvmYul.UInt256.ofNat slot ≠ IRStorageSlot.ofNat 0 := by + simpa [IRStorageSlot.ofNat] using hSlotNe + have hSlotNeUInt : + EvmYul.UInt256.ofNat slot ≠ EvmYul.UInt256.ofNat 0 := by + intro hEq + exact hSlotNe' (by simpa [IRStorageSlot.ofNat] using hEq) + simpa [Compiler.Proofs.abstractStoreStorageOrMapping, IRStorageSlot.ofNat, + hSlotNeUInt] using hLookup' + +/-- The direct lowered setter halt projects to the same observable storage, +success bit, return value, and logs as the selected IR setter body. -/ +private theorem nativeResultsMatchOn_execIRFunction_store0_calldataload4_stop_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (arg : Nat) (rest : List Nat) + (hBody : fn.body = [ + Yul.YulStmt.let_ "value" (Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]), + Yul.YulStmt.expr (Yul.YulExpr.call "sstore" [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (hArgs : tx.args = arg :: rest) : + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let initialWithStore := + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract yulTx state.storage slots switchId store + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let finalState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩)))) := by + intro yulTx slots initialWithStore withValue finalState + have hIR := + Compiler.Proofs.IRGeneration.execIRFunction_store0_calldataload4_stop_of_args_cons + fn tx state arg rest hBody hArgs + rw [hIR] + simp only [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn] + refine ⟨rfl, rfl, ?_, ?_⟩ + · intro slot hslot + have hslot' : slot ∈ slots := by + simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots, + hslot] + let markedStore := + (((store.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + have hNative := + projectStorageFromState_storeHit_initialState_materialized + nativeContract yulTx state.storage slots markedStore arg slot hslot' + have hArgMod : + EvmYul.UInt256.ofNat arg = + EvmYul.UInt256.ofNat (arg % evmModulus) := by + unfold EvmYul.UInt256.ofNat + simp [Id.run, Fin.ofNat, evmModulus, EvmYul.UInt256.size] + simpa [finalState, withValue, initialWithStore, markedStore, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + Compiler.Proofs.abstractStoreStorageOrMapping, + Compiler.Proofs.IRGeneration.IRStorageWord.ofNat, hArgMod] using + hNative.symm + · simp [finalState, withValue, initialWithStore, + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState, + EvmYul.Yul.State.setState, EvmYul.Yul.State.toState, + EvmYul.Yul.State.insert, EvmYul.State.sstore, + EvmYul.State.setAccount, EvmYul.State.lookupAccount, + EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, + EvmYul.Substate.addAccessedStorageKey, Option.option] + split <;> rfl + +/-- Build the direct selected-user-body halt bridge for the generated +`store(uint256)` setter body shape. -/ +private theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_store0_calldataload4_stop + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hStoreBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.let_ "value" (Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]), + Yul.YulStmt.expr (Yul.YulExpr.call "sstore" [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + rcases hArgsCons with ⟨arg, rest, hArgs⟩ + have hBody := hStoreBody fn hFind + have hLowerConcrete : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart + ([Yul.YulStmt.let_ "value" + (Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]), + Yul.YulStmt.expr + (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])] : List Yul.YulStmt) = + .ok (simpleStorageLoweredStoreCaseBodyTail3, userBodyStart) := by + simp [simpleStorageLoweredStoreCaseBodyTail3, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_let, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_expr, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + have hLowerPair : + (bodyNative, bodyEnd) = (simpleStorageLoweredStoreCaseBodyTail3, userBodyStart) := by + rw [hBody, hLowerConcrete] at hUserBodyLower + simpa using hUserBodyLower.symm + rcases hLowerPair with ⟨rfl, rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let initialWithStore := + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract yulTx state.storage slots switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let haltState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState ⟨0⟩)) + refine ⟨haltState, ⟨0⟩, nativeYul, ?_, rfl, ?_⟩ + · intro _pre suffix + simpa [switchId, yulTx, slots, initialWithStore, withValue, haltState, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_block_store0_calldataload4_stop_markedPrefix_halt + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length) + nativeContract yulTx state.storage slots switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + arg rest (by simpa [yulTx, YulTransaction.ofIR] using hArgs)) + · simpa [switchId, yulTx, slots, initialWithStore, withValue, haltState, + nativeYul] using + (nativeResultsMatchOn_execIRFunction_store0_calldataload4_stop_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + arg rest hBody hArgs) + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_store0_calldataload4_stop + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hStoreBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.let_ "value" (Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]), + Yul.YulStmt.expr (Yul.YulExpr.call "sstore" [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt irContract tx state + observableSlots + (NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_store0_calldataload4_stop + irContract tx state observableSlots hStoreBody hArgsCons) + +/-- Closed generated `callDispatcher` theorem for selected store-body success. + +This specializes the current public generated-dispatcher theorem to the +lowered `store(uint256)` body shape, discharging the selected user-body halt +bridge from the concrete native body proof above. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_store0_calldataload4_stop + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hStoreBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.let_ "value" (Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]), + Yul.YulStmt.expr (Yul.YulExpr.call "sstore" [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_store0_calldataload4_stop + irContract tx state observableSlots hStoreBody hArgsCons) + hThreshold + +/-- Closed-form evaluation of `projectResult` on the retrieve-hit halt error +produced by the lowered SimpleStorage retrieve body. The halt state is built +by chaining `sload(0)` (toState override), `mstore(0, _)` (toMachineState +override), and `evmReturn(0, 32)` (toMachineState override) starting from a +shared state with empty memory. The native projected return value is the +`Nat`-normalized form of the loaded slot-zero word; storage and logs are +read off the halt's `sharedState` directly. -/ +private theorem projectResult_retrieveHit_eq + (tx : YulTransaction) (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hMemory : shared.memory = ByteArray.empty) : + let p := shared.sload (EvmYul.UInt256.ofNat 0) + let shared1 : EvmYul.SharedState .Yul := { shared with toState := p.1 } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) p.2 } + let shared3 : EvmYul.SharedState .Yul := + { shared2 with + toMachineState := + shared2.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + tx initialStorage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared3 store) ⟨1⟩)) = + { success := true, + returnValue := some p.2.toNat, + finalStorage := + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + tx (EvmYul.Yul.State.Ok shared3 store), + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + tx (EvmYul.Yul.State.Ok shared3 store)), + events := + initialEvents ++ + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared3 store) } := by + intro p shared1 shared2 shared3 + -- shared1 inherits memory from shared because only `toState` was overridden. + have hMemory1 : shared1.memory = ByteArray.empty := hMemory + -- The harness helpers describe the result via `setMachineState` chains; + -- those equal the structural overrides used in `shared3`. + have hSize : + (EvmYul.Yul.State.Ok shared3 store).sharedState.H_return.size = 32 := by + have h := Compiler.Proofs.YulGeneration.Backends.Native.mstore0_then_return32_hReturn_size + shared1 store p.2 + simpa [shared3, shared2, EvmYul.Yul.State.setMachineState, + EvmYul.Yul.State.toMachineState, EvmYul.Yul.State.sharedState] using h + have hH_return : + (EvmYul.Yul.State.Ok shared3 store).sharedState.H_return = p.2.toByteArray := by + have h := + Compiler.Proofs.YulGeneration.Backends.Native.mstore0_then_return32_emptyMemory_hReturn_eq_toByteArray + shared1 store p.2 hMemory1 + simpa [shared3, shared2, EvmYul.Yul.State.setMachineState, + EvmYul.Yul.State.toMachineState, EvmYul.Yul.State.sharedState] using h + have hHaltNotZero : (⟨1⟩ : EvmYul.Yul.Ast.Literal) ≠ ⟨0⟩ := by + intro h + norm_num [EvmYul.UInt256.size] at h + have hReturnValue : + Compiler.Proofs.YulGeneration.Backends.Native.projectHaltReturn + (EvmYul.Yul.State.Ok shared3 store) ⟨1⟩ = some p.2.toNat := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.projectHaltReturn_32ByteReturn + (EvmYul.Yul.State.Ok shared3 store) ⟨1⟩ hHaltNotZero hSize] + rw [hH_return, + Compiler.Proofs.YulGeneration.Backends.Native.byteArrayWord_uint256_toByteArray] + simp only [Compiler.Proofs.YulGeneration.Backends.Native.projectResult, + hReturnValue] + +/-- Closed-form evaluation of `projectResult` on a selected literal-return +body halt produced by native `mstore(0, value); return(0, 32)`. -/ +private theorem projectResult_literalReturnHit_eq + (tx : YulTransaction) (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (value : Nat) + (hMemory : shared.memory = ByteArray.empty) : + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat value) } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + tx initialStorage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared2 store) ⟨1⟩)) = + { success := true, + returnValue := some (EvmYul.UInt256.ofNat value).toNat, + finalStorage := + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + tx (EvmYul.Yul.State.Ok shared2 store), + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + tx (EvmYul.Yul.State.Ok shared2 store)), + events := + initialEvents ++ + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared2 store) } := by + intro shared1 shared2 + have hSize : + (EvmYul.Yul.State.Ok shared2 store).sharedState.H_return.size = 32 := by + have h := Compiler.Proofs.YulGeneration.Backends.Native.mstore0_then_return32_hReturn_size + shared store (EvmYul.UInt256.ofNat value) + simpa [shared2, shared1, EvmYul.Yul.State.setMachineState, + EvmYul.Yul.State.toMachineState, EvmYul.Yul.State.sharedState] using h + have hH_return : + (EvmYul.Yul.State.Ok shared2 store).sharedState.H_return = + (EvmYul.UInt256.ofNat value).toByteArray := by + have h := + Compiler.Proofs.YulGeneration.Backends.Native.mstore0_then_return32_emptyMemory_hReturn_eq_toByteArray + shared store (EvmYul.UInt256.ofNat value) hMemory + simpa [shared2, shared1, EvmYul.Yul.State.setMachineState, + EvmYul.Yul.State.toMachineState, EvmYul.Yul.State.sharedState] using h + have hHaltNotZero : (⟨1⟩ : EvmYul.Yul.Ast.Literal) ≠ ⟨0⟩ := by + intro h + norm_num [EvmYul.UInt256.size] at h + have hReturnValue : + Compiler.Proofs.YulGeneration.Backends.Native.projectHaltReturn + (EvmYul.Yul.State.Ok shared2 store) ⟨1⟩ = + some (EvmYul.UInt256.ofNat value).toNat := by + rw [Compiler.Proofs.YulGeneration.Backends.Native.projectHaltReturn_32ByteReturn + (EvmYul.Yul.State.Ok shared2 store) ⟨1⟩ hHaltNotZero hSize] + rw [hH_return, + Compiler.Proofs.YulGeneration.Backends.Native.byteArrayWord_uint256_toByteArray] + simp only [Compiler.Proofs.YulGeneration.Backends.Native.projectResult, + hReturnValue] + +/-- The direct lowered retrieve halt projects to the same observable result as +the selected IR retrieve body. -/ +private theorem nativeResultsMatchOn_execIRFunction_mstore0_sload0_return32_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hBody : fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((store.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let p := shared.sload (EvmYul.UInt256.ofNat 0) + let shared1 : EvmYul.SharedState .Yul := { shared with toState := p.1 } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) p.2 } + let shared3 : EvmYul.SharedState .Yul := + { shared2 with + toMachineState := + shared2.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared3 markedStore) ⟨1⟩)))) := by + intro yulTx slots markedStore shared p shared1 shared2 shared3 + have hIR := + Compiler.Proofs.IRGeneration.execIRFunction_mstore0_sload0_return32 + fn tx state hBody + have hProject : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared3 markedStore) ⟨1⟩)) = + { success := true, + returnValue := some p.2.toNat, + finalStorage := + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared3 markedStore), + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared3 markedStore)), + events := + state.events ++ + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared3 markedStore) } := by + have hMemory : shared.memory = ByteArray.empty := by + simp [shared, Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + simpa [yulTx, shared, p, shared1, shared2, shared3] using + projectResult_retrieveHit_eq yulTx state.storage state.events + shared markedStore hMemory + have hSlotZero : 0 ∈ slots := by + simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots] + have hp : + p.2 = state.storage (IRStorageSlot.ofNat 0) := by + have hload := + Compiler.Proofs.YulGeneration.Backends.Native.initialState_sload_materializedSlot_value + nativeContract yulTx state.storage slots 0 hSlotZero + simpa [p, shared, Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256] + using hload + have hLogs : + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared3 markedStore) = [] := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState, + shared3, shared2, shared1, p, shared, + Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.State.sload, EvmYul.State.addAccessedStorageKey, + EvmYul.Substate.addAccessedStorageKey, EvmYul.Yul.State.sharedState] + rfl + rw [hIR, hProject] + refine ⟨rfl, ?_, ?_, ?_⟩ + · simp [hp, Compiler.Proofs.IRGeneration.IRStorageWord.toNat] + · intro slot hslot + have hslot' : slot ∈ slots := by + simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots, + hslot] + have hNative := + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState_retrieveHit_initialState_materialized + nativeContract yulTx state.storage slots markedStore slot hslot' + exact hNative.symm + · rw [hLogs, List.append_nil] + +/-- Generated zero-parameter literal-return functions first run + `genParamLoads []`, whose calldata guard skips for well-sized ABI calldata, + then execute the literal-return payload. -/ +private theorem execIRFunction_zeroParam_mstore0_lit_return32 + (fn : IRFunction) (tx : IRTransaction) (initialState : IRState) + (value : Nat) + (hParams : fn.params = []) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hBody : fn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + execIRFunction fn tx.args (applyIRTransactionContext tx initialState) = + { success := true + returnValue := some value + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + let rest : List Yul.YulStmt := + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] + let params : List CompilationModel.Param := [] + let body := Compiler.CompilationModel.genParamLoads params ++ rest + unfold execIRFunction + simp only [hParams, hBody, List.zip_nil_left] + change + (match execIRStmts (sizeOf body + 1) + (applyIRTransactionContext tx initialState) body with + | .continue s => + ({ + success := true + returnValue := s.returnValue + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } : IRResult) + | .return v s => + ({ + success := true + returnValue := some v + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } : IRResult) + | .stop s => + ({ + success := true + returnValue := none + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } : IRResult) + | .revert _ => + ({ + success := false + returnValue := none + finalStorage := (applyIRTransactionContext tx initialState).storage + finalMappings := + Compiler.Proofs.storageAsMappings + (applyIRTransactionContext tx initialState).storage + events := (applyIRTransactionContext tx initialState).events } : IRResult)) = + ({ + success := true + returnValue := some value + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } : IRResult) + have hFuel : + sizeOf body + 1 = + (Compiler.CompilationModel.genParamLoads params).length + rest.length + + (sizeOf body - body.length) + 1 := by + simp [body, params, rest, Compiler.CompilationModel.genParamLoads, + Compiler.CompilationModel.genParamLoadsFrom, + Compiler.CompilationModel.genParamLoadBodyFrom] + omega + have hParam : + execIRStmts + ((Compiler.CompilationModel.genParamLoads params).length + + rest.length + (sizeOf body - body.length) + 1) + (applyIRTransactionContext tx initialState) + body = + execIRStmts + (rest.length + (sizeOf body - body.length) + + 1) + (Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState + (applyIRTransactionContext tx initialState) []) + rest := by + simpa [params, body] using + Compiler.Proofs.IRGeneration.ParamLoading.exec_genParamLoads_supported_then_extraFuel + (state := applyIRTransactionContext tx initialState) + (params := params) (bindings := []) (rest := rest) + (extraFuel := sizeOf body - body.length) + (by intro param hmem; simp [params] at hmem) + (by + simpa [Compiler.Constants.evmModulus, EvmYul.UInt256.size, + applyIRTransactionContext] using hNoWrap) + (by simp [params, SourceSemantics.bindSupportedParams]) + have hRaw : + execIRStmts (rest.length + (sizeOf body - body.length) + 1) + (Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState + (applyIRTransactionContext tx initialState) []) + rest = + .return value + { (applyIRTransactionContext tx initialState) with + memory := fun o => if o = 0 then value else + (applyIRTransactionContext tx initialState).memory o } := by + have hEnough : 2 ≤ rest.length + (sizeOf body - body.length) := by + simp [rest] + obtain ⟨k, hk⟩ : + ∃ k, rest.length + (sizeOf body - body.length) = k + 2 := + ⟨rest.length + (sizeOf body - body.length) - 2, by omega⟩ + rw [hk] + simp +decide [Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState, + rest, execIRStmts, execIRStmt, evalIRExpr] + rw [hFuel, hParam, hRaw] + simp [applyIRTransactionContext] + +/-- Generated zero-parameter storage-return functions first run + `genParamLoads []`, whose calldata guard skips for well-sized ABI calldata, + then execute the storage-return payload. -/ +private theorem execIRFunction_zeroParam_mstore0_sload0_return32 + (fn : IRFunction) (tx : IRTransaction) (initialState : IRState) + (hParams : fn.params = []) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hBody : fn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + execIRFunction fn tx.args (applyIRTransactionContext tx initialState) = + { success := true + returnValue := some ((initialState.storage (IRStorageSlot.ofNat 0)).toNat) + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + let rest : List Yul.YulStmt := + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] + let params : List CompilationModel.Param := [] + let body := Compiler.CompilationModel.genParamLoads params ++ rest + unfold execIRFunction + simp only [hParams, hBody, List.zip_nil_left] + change + (match execIRStmts (sizeOf body + 1) + (applyIRTransactionContext tx initialState) body with + | .continue s => + ({ + success := true + returnValue := s.returnValue + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } : IRResult) + | .return v s => + ({ + success := true + returnValue := some v + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } : IRResult) + | .stop s => + ({ + success := true + returnValue := none + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } : IRResult) + | .revert _ => + ({ + success := false + returnValue := none + finalStorage := (applyIRTransactionContext tx initialState).storage + finalMappings := + Compiler.Proofs.storageAsMappings + (applyIRTransactionContext tx initialState).storage + events := (applyIRTransactionContext tx initialState).events } : IRResult)) = + ({ + success := true + returnValue := some ((initialState.storage (IRStorageSlot.ofNat 0)).toNat) + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } : IRResult) + have hFuel : + sizeOf body + 1 = + (Compiler.CompilationModel.genParamLoads params).length + rest.length + + (sizeOf body - body.length) + 1 := by + simp [body, params, rest, Compiler.CompilationModel.genParamLoads, + Compiler.CompilationModel.genParamLoadsFrom, + Compiler.CompilationModel.genParamLoadBodyFrom] + omega + have hParam : + execIRStmts + ((Compiler.CompilationModel.genParamLoads params).length + + rest.length + (sizeOf body - body.length) + 1) + (applyIRTransactionContext tx initialState) + body = + execIRStmts + (rest.length + (sizeOf body - body.length) + + 1) + (Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState + (applyIRTransactionContext tx initialState) []) + rest := by + simpa [params, body] using + Compiler.Proofs.IRGeneration.ParamLoading.exec_genParamLoads_supported_then_extraFuel + (state := applyIRTransactionContext tx initialState) + (params := params) (bindings := []) (rest := rest) + (extraFuel := sizeOf body - body.length) + (by intro param hmem; simp [params] at hmem) + (by + simpa [Compiler.Constants.evmModulus, EvmYul.UInt256.size, + applyIRTransactionContext] using hNoWrap) + (by simp [params, SourceSemantics.bindSupportedParams]) + have hRaw : + execIRStmts (rest.length + (sizeOf body - body.length) + 1) + (Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState + (applyIRTransactionContext tx initialState) []) + rest = + .return + (((applyIRTransactionContext tx initialState).storage + (IRStorageSlot.ofNat 0)).toNat) + { (applyIRTransactionContext tx initialState) with + memory := fun o => if o = 0 then + (((applyIRTransactionContext tx initialState).storage + (IRStorageSlot.ofNat 0)).toNat) + else (applyIRTransactionContext tx initialState).memory o } := by + have hEnough : 2 ≤ rest.length + (sizeOf body - body.length) := by + simp [rest] + obtain ⟨k, hk⟩ : + ∃ k, rest.length + (sizeOf body - body.length) = k + 2 := + ⟨rest.length + (sizeOf body - body.length) - 2, by omega⟩ + rw [hk] + simp +decide [Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState, + rest, execIRStmts, execIRStmt, evalIRExpr, evalIRCall_sload_singleton, + Compiler.Proofs.abstractLoadStorageOrMapping] + rw [hFuel, hParam, hRaw] + simp [applyIRTransactionContext] + +set_option maxRecDepth 10000 + +/-- Generated one-argument setter functions first run + `genParamLoads [{name := "value", ty := .uint256}]`, then store the decoded + value in slot zero and stop. -/ +private theorem execIRFunction_oneParam_store0_value_stop + (fn : IRFunction) (tx : IRTransaction) (initialState : IRState) + (arg : Nat) (rest : List Nat) + (hParams : + fn.params = + [{ name := "value", ty := IRType.uint256 }]) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : tx.args = arg :: rest) + (hBody : fn.body = + Compiler.CompilationModel.genParamLoads + [{ name := "value", ty := CompilationModel.ParamType.uint256 }] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) : + execIRFunction fn tx.args (applyIRTransactionContext tx initialState) = + { success := true + returnValue := none + finalStorage := + Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 + (arg % Compiler.Constants.evmModulus) + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 + (arg % Compiler.Constants.evmModulus)) + events := initialState.events } := by + let params : List CompilationModel.Param := + [{ name := "value", ty := CompilationModel.ParamType.uint256 }] + let irParams : List IRParam := + [{ name := "value", ty := IRType.uint256 }] + let restBody : List Yul.YulStmt := + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])] + let body := Compiler.CompilationModel.genParamLoads params ++ restBody + let txState := applyIRTransactionContext tx initialState + let stateWithParams := + ((irParams.zip tx.args).foldl + (fun s pair => s.setVar pair.1.name pair.2) txState) + unfold execIRFunction + simp only [hParams, hBody] + change + (match execIRStmts (sizeOf body + 1) stateWithParams body with + | .continue s => + ({ + success := true + returnValue := s.returnValue + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } : IRResult) + | .return v s => + ({ + success := true + returnValue := some v + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } : IRResult) + | .stop s => + ({ + success := true + returnValue := none + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } : IRResult) + | .revert _ => + ({ + success := false + returnValue := none + finalStorage := txState.storage + finalMappings := Compiler.Proofs.storageAsMappings txState.storage + events := txState.events } : IRResult)) = + ({ + success := true + returnValue := none + finalStorage := + Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 + (arg % Compiler.Constants.evmModulus) + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 + (arg % Compiler.Constants.evmModulus)) + events := initialState.events } : IRResult) + have hFuel : + sizeOf body + 1 = + (Compiler.CompilationModel.genParamLoads params).length + + restBody.length + (sizeOf body - body.length) + 1 := by + simp [body, params, restBody, Compiler.CompilationModel.genParamLoads, + Compiler.CompilationModel.genParamLoadsFrom, + Compiler.CompilationModel.genParamLoadBodyFrom, + Compiler.CompilationModel.genSingleParamLoad, + Compiler.CompilationModel.genScalarLoad] + omega + have hBind : + SourceSemantics.bindSupportedParams params stateWithParams.calldata = + some [("value", arg % Compiler.Constants.evmModulus)] := by + simp [params, stateWithParams, txState, hArgs, applyIRTransactionContext, + SourceSemantics.bindSupportedParams, + SourceSemantics.decodeSupportedParamWord, Compiler.Constants.evmModulus] + have hParam : + execIRStmts + ((Compiler.CompilationModel.genParamLoads params).length + + restBody.length + (sizeOf body - body.length) + 1) + stateWithParams body = + execIRStmts + (restBody.length + (sizeOf body - body.length) + 1) + (Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState + stateWithParams [("value", arg % Compiler.Constants.evmModulus)]) + restBody := by + simpa [params, body] using + Compiler.Proofs.IRGeneration.ParamLoading.exec_genParamLoads_supported_then_extraFuel + (state := stateWithParams) + (params := params) + (bindings := [("value", arg % Compiler.Constants.evmModulus)]) + (rest := restBody) + (extraFuel := sizeOf body - body.length) + (by + intro param hmem + simp [params] at hmem + subst param + simp [SupportedExternalParamType]) + (by + simpa [Compiler.Constants.evmModulus, EvmYul.UInt256.size, + stateWithParams, txState, applyIRTransactionContext] using hNoWrap) + hBind + have hRaw : + execIRStmts + (restBody.length + (sizeOf body - body.length) + 1) + (Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState + stateWithParams [("value", arg % Compiler.Constants.evmModulus)]) + restBody = + .stop + { Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState + stateWithParams [("value", arg % Compiler.Constants.evmModulus)] with + storage := + Compiler.Proofs.abstractStoreStorageOrMapping + (Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState + stateWithParams [("value", arg % Compiler.Constants.evmModulus)]).storage + 0 (arg % Compiler.Constants.evmModulus) } := by + have hEnough : 2 ≤ restBody.length + (sizeOf body - body.length) := by + simp [restBody] + obtain ⟨k, hk⟩ : + ∃ k, restBody.length + (sizeOf body - body.length) = k + 2 := + ⟨restBody.length + (sizeOf body - body.length) - 2, by omega⟩ + rw [hk] + simp +decide [Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState, + restBody, execIRStmts, execIRStmt, evalIRExpr, IRState.getVar, + IRState.setVar] + rw [hFuel, hParam, hRaw] + simp [Compiler.Proofs.IRGeneration.ParamLoading.applyBindingsToIRState, + stateWithParams, txState, applyIRTransactionContext, IRState.setVar, + irParams, hArgs, Compiler.Proofs.abstractStoreStorageOrMapping_eq] + +/-- The generated one-argument setter halt projects to the same observable +storage, success bit, return value, and logs as the selected generated IR +setter body. -/ +private theorem nativeResultsMatchOn_execIRFunction_oneParam_store0_value_stop_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (arg : Nat) (rest : List Nat) + (hParams : + fn.params = + [{ name := "value", ty := IRType.uint256 }]) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : tx.args = arg :: rest) + (hBody : fn.body = + Compiler.CompilationModel.genParamLoads + [{ name := "value", ty := CompilationModel.ParamType.uint256 }] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) : + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let initialWithStore := + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId + nativeContract yulTx state.storage slots switchId store + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let finalState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩)))) := by + intro yulTx slots initialWithStore withValue finalState + have hIR := + execIRFunction_oneParam_store0_value_stop + fn tx state arg rest hParams hNoWrap hArgs hBody + rw [hIR] + simp only [nativeResultsMatchOn, + Compiler.Proofs.YulGeneration.Backends.Native.nativeResultsMatchOn] + refine ⟨rfl, rfl, ?_, ?_⟩ + · intro slot hslot + have hslot' : slot ∈ slots := by + simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots, + hslot] + let markedStore := + (((store.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + have hNative := + projectStorageFromState_storeHit_initialState_materialized + nativeContract yulTx state.storage slots markedStore arg slot hslot' + have hArgMod : + EvmYul.UInt256.ofNat arg = + EvmYul.UInt256.ofNat (arg % evmModulus) := by + unfold EvmYul.UInt256.ofNat + simp [Id.run, Fin.ofNat, evmModulus, EvmYul.UInt256.size] + simpa [finalState, withValue, initialWithStore, markedStore, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + Compiler.Proofs.abstractStoreStorageOrMapping, + Compiler.Proofs.IRGeneration.IRStorageWord.ofNat, hArgMod] using + hNative.symm + · simp [finalState, withValue, initialWithStore, + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStorePrefixStateForId, + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreInitialState, + Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState, + EvmYul.Yul.State.setState, EvmYul.Yul.State.toState, + EvmYul.Yul.State.insert, EvmYul.State.sstore, + EvmYul.State.setAccount, EvmYul.State.lookupAccount, + EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, + EvmYul.Substate.addAccessedStorageKey, Option.option] + split <;> rfl + +/-- Build the selected-user-body halt bridge for generated one-argument +`store(uint256)` setter bodies. -/ +private theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_oneParam_store0_value_stop + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hParams : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params = [{ name := "value", ty := IRType.uint256 }]) + (hStoreBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = + Compiler.CompilationModel.genParamLoads + [{ name := "value", ty := CompilationModel.ParamType.uint256 }] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + rcases hArgsCons with ⟨arg, rest, hArgs⟩ + have hFnParams := hParams fn hFind + have hBody := hStoreBody fn hFind + have hLowerConcrete : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart + (Compiler.CompilationModel.genParamLoads + [{ name := "value", ty := CompilationModel.ParamType.uint256 }] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])] : List Yul.YulStmt) = + .ok (simpleStorageLoweredStoreCaseBodyTail2, userBodyStart) := by + simp [simpleStorageLoweredStoreCaseBodyTail2, + Compiler.CompilationModel.genParamLoads, + Compiler.CompilationModel.genParamLoadsFrom, + Compiler.CompilationModel.genParamLoadBodyFrom, + Compiler.CompilationModel.genSingleParamLoad, + Compiler.CompilationModel.genScalarLoad, + Compiler.CompilationModel.paramHeadSize, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_expr, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_if, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_let, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + have hLowerPair : + (bodyNative, bodyEnd) = + (simpleStorageLoweredStoreCaseBodyTail2, userBodyStart) := by + rw [hBody, hLowerConcrete] at hUserBodyLower + simpa using hUserBodyLower.symm + rcases hLowerPair with ⟨rfl, rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let initialWithStore : EvmYul.Yul.State := .Ok shared markedStore + let withValue := initialWithStore.insert "value" + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) + let haltState := withValue.setState + (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) + (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState ⟨0⟩)) + refine ⟨haltState, ⟨0⟩, nativeYul, ?_, rfl, ?_⟩ + · intro _pre suffix + have hExec := + exec_block_simpleStorageLoweredStoreCaseBodyTail2_markedPrefix_halt + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length) + nativeContract yulTx state.storage slots switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + arg rest (by simpa [yulTx, YulTransaction.ofIR] using hArgs) + (by simpa [yulTx, YulTransaction.ofIR_args] using hNoWrap) + change + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block simpleStorageLoweredStoreCaseBodyTail2) + (some nativeContract) (EvmYul.Yul.State.Ok shared markedStore) = + .error (EvmYul.Yul.Exception.YulHalt haltState ⟨0⟩) + simpa [switchId, yulTx, slots, markedStore, shared, initialWithStore, + withValue, haltState, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hExec + · simpa [switchId, yulTx, slots, initialWithStore, withValue, haltState, + nativeYul] using + (nativeResultsMatchOn_execIRFunction_oneParam_store0_value_stop_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + arg rest hFnParams hNoWrap hArgs hBody) + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_oneParam_store0_value_stop + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hParams : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params = [{ name := "value", ty := IRType.uint256 }]) + (hStoreBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = + Compiler.CompilationModel.genParamLoads + [{ name := "value", ty := CompilationModel.ParamType.uint256 }] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt irContract tx state + observableSlots + (NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_oneParam_store0_value_stop + irContract tx state observableSlots hNoWrap hParams hStoreBody hArgsCons) + +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_oneParam_store0_value_stop + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hParams : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params = [{ name := "value", ty := IRType.uint256 }]) + (hStoreBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = + Compiler.CompilationModel.genParamLoads + [{ name := "value", ty := CompilationModel.ParamType.uint256 }] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_oneParam_store0_value_stop + irContract tx state observableSlots hNoWrap hParams hStoreBody hArgsCons) + hThreshold + +private theorem selectedCompiledFunction_oneParam_store0_value_stop_shape_of_forall₂ + (fields : List CompilationModel.Field) + (events : List CompilationModel.EventDef) + (errors : List CompilationModel.ErrorDef) + (tx : IRTransaction) + {pairs : List (CompilationModel.FunctionSpec × Nat)} + {irFns : List IRFunction} + (hcompiled : + List.Forall₂ + (fun entry irFn => + CompilationModel.compileFunctionSpec fields events errors + [] entry.2 entry.1 = Except.ok irFn) + pairs irFns) + (hSourceParams : + ∀ entry, entry ∈ pairs → entry.2 = tx.functionSelector → + entry.1.params = + [{ name := "value", ty := CompilationModel.ParamType.uint256 }]) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ pairs → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList fields events errors .calldata + [] false (entry.1.params.map (·.name)) [] entry.1.body = + Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (irFn : IRFunction) + (hFind : + irFns.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn) : + irFn.params = [{ name := "value", ty := IRType.uint256 }] ∧ + irFn.body = + Compiler.CompilationModel.genParamLoads + [{ name := "value", ty := CompilationModel.ParamType.uint256 }] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])] := by + induction hcompiled with + | nil => + simp at hFind + | @cons entry headIr tailPairs tailIr hhead htail ih => + by_cases hSelector : headIr.selector = tx.functionSelector + · simp [hSelector] at hFind + rcases hFind with rfl + have hEntrySelector : entry.2 = tx.functionSelector := by + have hSel := + Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_selector + fields events errors entry.2 entry.1 headIr hhead + simpa [hSelector] using hSel.symm + rcases + Compiler.Proofs.IRGeneration.FunctionShape.compileFunctionSpec_ok_components + fields events errors entry.2 entry.1 headIr hhead with + ⟨returns, bodyStmts, _hvalidate, _hreturns, hbody, hirFn⟩ + have hEntryMem : entry ∈ entry :: tailPairs := by simp + have hSpecParams : + entry.1.params = + [{ name := "value", ty := CompilationModel.ParamType.uint256 }] := + hSourceParams entry hEntryMem hEntrySelector + have hBodyStmts : + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])] := + hSourceBody entry bodyStmts hEntryMem hEntrySelector hbody + constructor + · rw [hirFn] + simp [Compiler.Proofs.IRGeneration.FunctionShape.compiledFunctionIR, + hSpecParams, CompilationModel.Param.toIRParam, + CompilationModel.ParamType.toIRType] + · rw [hirFn] + simp [Compiler.Proofs.IRGeneration.FunctionShape.compiledFunctionIR, + hSpecParams, hBodyStmts] + · have hFindTail : + tailIr.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn := by + simpa [hSelector] using hFind + exact ih + (fun entry' hMem => + hSourceParams entry' (by simp [hMem])) + (fun entry' bodyStmts hMem => + hSourceBody entry' bodyStmts (by simp [hMem])) + hFindTail + +private theorem selectedGeneratedFunction_oneParam_store0_value_stop_shape_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSourceParams : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + entry.1.params = + [{ name := "value", ty := CompilationModel.ParamType.uint256 }]) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .calldata [] false (entry.1.params.map (·.name)) [] + entry.1.body = Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (irFn : IRFunction) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn) : + irFn.params = [{ name := "value", ty := IRType.uint256 }] ∧ + irFn.body = + Compiler.CompilationModel.genParamLoads + [{ name := "value", ty := CompilationModel.ParamType.uint256 }] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])] := by + have hcompiled := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions + spec selectors hSupported irContract hcompile + exact + selectedCompiledFunction_oneParam_store0_value_stop_shape_of_forall₂ + spec.fields spec.events spec.errors tx hcompiled hSourceParams + hSourceBody irFn hFind + +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_oneParam_store0_value_stop + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hSourceParams : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + entry.1.params = + [{ name := "value", ty := CompilationModel.ParamType.uint256 }]) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .calldata [] false (entry.1.params.map (·.name)) [] + entry.1.body = Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_oneParam_store0_value_stop + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (fun fn hFind => + (selectedGeneratedFunction_oneParam_store0_value_stop_shape_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile hSourceParams + hSourceBody fn hFind).1) + (fun fn hFind => + (selectedGeneratedFunction_oneParam_store0_value_stop_shape_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile hSourceParams + hSourceBody fn hFind).2) + hArgsCons + +private theorem compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher_source_oneParam_store0_value_stop + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSourceParams : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + entry.1.params = + [{ name := "value", ty := CompilationModel.ParamType.uint256 }]) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .calldata [] false (entry.1.params.map (·.name)) [] + entry.1.body = Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "sstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.ident "value"]), + Yul.YulStmt.expr (Yul.YulExpr.call "stop" [])]) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics spec selectors hSupported tx + initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots nativeContract) := by + rcases + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_oneParam_store0_value_stop + spec selectors hSupported irContract tx + (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots hcompile hSelectorRange hSelectorsRange hNoWrap + (fun fn hFind => + generatedFunctionCalldataThreshold_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile fn hFind) + hSourceParams hSourceBody hArgsCons with + ⟨nativeContract, hLower, hMatch⟩ + exact + ⟨nativeContract, hLower, + compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match + spec selectors hSupported irContract tx initialWorld observableSlots + nativeContract htxNormalized hcalldataSizeFits hcompile hMatch⟩ + +/-- The direct lowered literal-return halt projects to the same observable +result as the selected IR body `mstore(0, value); return(0, 32)`. -/ +private theorem nativeResultsMatchOn_execIRFunction_mstore0_lit_return32_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (value : Nat) + (hValueRange : value < EvmYul.UInt256.size) + (hBody : fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((store.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat value) } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared2 markedStore) ⟨1⟩)))) := by + intro yulTx slots markedStore shared shared1 shared2 + have hIR := + Compiler.Proofs.IRGeneration.execIRFunction_mstore0_lit_return32 + fn tx state value hBody + have hProject : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared2 markedStore) ⟨1⟩)) = + { success := true, + returnValue := some (EvmYul.UInt256.ofNat value).toNat, + finalStorage := + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore), + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore)), + events := + state.events ++ + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared2 markedStore) } := by + have hMemory : shared.memory = ByteArray.empty := by + simp [shared, Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + simpa [yulTx, shared, shared1, shared2] using + projectResult_literalReturnHit_eq yulTx state.storage state.events + shared markedStore value hMemory + have hValueNat : (EvmYul.UInt256.ofNat value).toNat = value := by + have hValueRange' : value < Verity.Core.UINT256_MODULUS := by + simpa [EvmYul.UInt256.size, Verity.Core.UINT256_MODULUS] using hValueRange + simp [EvmYul.UInt256.toNat, EvmYul.UInt256.ofNat, Fin.ofNat, + Nat.mod_eq_of_lt hValueRange'] + rfl + have hLogs : + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared2 markedStore) = [] := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState, + shared2, shared1, shared, + Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + rfl + rw [hIR, hProject] + refine ⟨rfl, ?_, ?_, ?_⟩ + · simp [hValueNat] + · intro slot hslot + have hslot' : slot ∈ slots := by + simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots, + hslot] + have hAccountMap : + shared2.accountMap = (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error (EvmYul.Yul.Exception.YulHalt haltState ⟨0⟩) ∧ - haltState = - let initialWithStore : EvmYul.Yul.State := - .Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState store_body - let withValue := initialWithStore.insert "value" - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) - withValue.setState - (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) := by - set g := simpleStorageNativeDispatcherFuel - 25 with hg_def - have hReshape : simpleStorageNativeDispatcherFuel = g + 25 := - (Nat.sub_add_cancel simpleStorageNativeDispatcherFuel_ge_25).symm - rw [hReshape] - obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := - simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - (g + 11) tx storage observableSlots hNoWrap - obtain ⟨storeBody', retrieveBody', hCases⟩ := - simpleStorageBuildSwitchSourceCases_lowered_shape reservedNames _ midN - cases' hLowerCases - subst hCases - obtain ⟨hStoreBody, hRetrieveBody⟩ := - simpleStorageLoweredHitCasesShape_concrete hLowerCases - subst hStoreBody - subst hRetrieveBody - set switchId := Backends.freshNativeSwitchId reservedNames n0 with hSw - let store_body : EvmYul.Yul.VarStore := - ((((∅ : EvmYul.Yul.VarStore).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)).insert - (Backends.nativeSwitchDiscrTempName switchId) - (EvmYul.UInt256.ofNat - (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + nativeContract yulTx state.storage slots).sharedState.accountMap := by + simp [shared2, shared1, shared] + have hNative := + Compiler.Proofs.YulGeneration.Backends.Native.initialState_materializedStorageSlot + nativeContract yulTx state.storage slots slot hslot' + have hNative' : + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore) + (IRStorageSlot.ofNat slot) = + state.storage (IRStorageSlot.ofNat slot) := by + simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState, + EvmYul.Yul.State.sharedState, hAccountMap] using hNative + exact hNative'.symm + · rw [hLogs, List.append_nil] + +/-- The lowered zero-parameter literal-return halt projects to the same +observable result as the generated IR body +`genParamLoads [] ++ [mstore(0, value); return(0, 32)]`. -/ +private theorem nativeResultsMatchOn_execIRFunction_zeroParam_mstore0_lit_return32_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (value : Nat) + (hValueRange : value < EvmYul.UInt256.size) + (hParams : fn.params = []) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hBody : fn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((store.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert (Backends.nativeSwitchMatchedTempName switchId) (EvmYul.UInt256.ofNat 0)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1) - let initialWithStore : EvmYul.Yul.State := - .Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState store_body - let withValue := initialWithStore.insert "value" - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) - let finalState := withValue.setState - (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) - refine ⟨store_body, finalState, ?_, ?_⟩ - · have hWei : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.weiValue = - (⟨0⟩ : EvmYul.Literal) := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_weiValue] - apply congrArg EvmYul.UInt256.mk - apply Fin.ext - simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256, - EvmYul.UInt256.ofNat, Fin.ofNat] using hMsgValue - have hSize : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.calldata.size < - EvmYul.UInt256.size := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] - exact hNoWrap - have hGe : - 36 ≤ (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.calldata.size := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] - rw [hArgs] - simp - omega - have hBodyHalt := - exec_block_simpleStorageLoweredStoreCaseBody_halt g - (some Compiler.SimpleStorageNativeWitness.nativeContract) - tx storage observableSlots store_body arg rest hArgs hWei hSize hGe - have hReduction := hExec - rw [show (g + 11 + 14 : Nat) = (g + 4) + 2 + 19 from by omega, - show (g + 11 + 8 : Nat) = (g + 4) + 2 + 13 from by omega, - show (2 : Nat) = ([(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : - List (Nat × List EvmYul.Yul.Ast.Stmt)).length from rfl] at hReduction - have hBodyExec : ∀ pre suffix, - ([(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : - List (Nat × List EvmYul.Yul.Ast.Stmt)) = - pre ++ (0x6057361d, simpleStorageLoweredStoreCaseBody) :: suffix → - EvmYul.Yul.exec (((g + 4) + 1) + suffix.length + 7) - (.Block simpleStorageLoweredStoreCaseBody) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState switchId tx storage - observableSlots) = - .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by - rintro pre suffix hDecomp - cases pre with - | nil => - simp only [List.nil_append, List.cons.injEq] at hDecomp - obtain ⟨_, hSuf⟩ := hDecomp - subst hSuf - simpa [simpleStorageDispatcherHitBodyInputState, initialWithStore, - withValue, finalState] using hBodyHalt - | cons _ restPre => - exfalso - simp only [List.cons_append, List.cons.injEq] at hDecomp - obtain ⟨_, hRest⟩ := hDecomp - cases restPre with - | nil => - simp only [List.nil_append, List.cons.injEq, Prod.mk.injEq] at hRest - exact absurd hRest.1.1 (by decide) - | cons _ _ => simp at hRest - have h := simpleStorageNativeContract_dispatcherExec_storeHit_error_via_reduction - (g + 4) switchId - [(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] - simpleStorageLoweredStoreCaseBody simpleStorageLoweredRetrieveCaseBody - tx storage observableSlots - (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) - hSelector rfl hBodyExec hReduction - have hLen : - ([(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : - List (Nat × List EvmYul.Yul.Ast.Stmt)).length = 2 := rfl - rw [hLen, show (g + 4) + 2 + 19 = g + 25 from by omega] at h - exact h - · rfl + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat value) } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared2 markedStore) ⟨1⟩)))) := by + intro yulTx slots markedStore shared shared1 shared2 + have hIR := + execIRFunction_zeroParam_mstore0_lit_return32 + fn tx state value hParams hNoWrap hBody + have hProject : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared2 markedStore) ⟨1⟩)) = + { success := true, + returnValue := some (EvmYul.UInt256.ofNat value).toNat, + finalStorage := + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore), + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore)), + events := + state.events ++ + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared2 markedStore) } := by + have hMemory : shared.memory = ByteArray.empty := by + simp [shared, Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + simpa [yulTx, shared, shared1, shared2] using + projectResult_literalReturnHit_eq yulTx state.storage state.events + shared markedStore value hMemory + have hValueNat : (EvmYul.UInt256.ofNat value).toNat = value := by + have hValueRange' : value < Verity.Core.UINT256_MODULUS := by + simpa [EvmYul.UInt256.size, Verity.Core.UINT256_MODULUS] using hValueRange + simp [EvmYul.UInt256.toNat, EvmYul.UInt256.ofNat, Fin.ofNat, + Nat.mod_eq_of_lt hValueRange'] + rfl + have hLogs : + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared2 markedStore) = [] := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState, + shared2, shared1, shared, + Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + rfl + rw [hIR, hProject] + refine ⟨rfl, ?_, ?_, ?_⟩ + · simp [hValueNat] + · intro slot hslot + have hslot' : slot ∈ slots := by + simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots, + hslot] + have hAccountMap : + shared2.accountMap = + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState.accountMap := by + simp [shared2, shared1, shared] + have hNative := + Compiler.Proofs.YulGeneration.Backends.Native.initialState_materializedStorageSlot + nativeContract yulTx state.storage slots slot hslot' + have hNative' : + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore) + (IRStorageSlot.ofNat slot) = + state.storage (IRStorageSlot.ofNat slot) := by + simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState, + EvmYul.Yul.State.sharedState, hAccountMap] using hNative + exact hNative'.symm + · rw [hLogs, List.append_nil] -/-- Native dispatcher exec at exactly `simpleStorageNativeDispatcherFuel` -reverts for the store-hit class when calldata contains no setter argument. -/ -theorem simpleStorageNativeContract_dispatcherExec_storeHit_short_revert_atFuel - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (hArgs : tx.args = []) - (hSelector : 0x6057361d = tx.functionSelector % Compiler.Constants.selectorModulus) +/-- The lowered zero-parameter storage-return halt projects to the same +observable result as the generated IR body +`genParamLoads [] ++ [mstore(0, sload(0)); return(0, 32)]`. -/ +private theorem nativeResultsMatchOn_execIRFunction_zeroParam_mstore0_sload0_return32_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hParams : fn.params = []) (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) - (hMsgValue : tx.msgValue % EvmYul.UInt256.size = 0) : - Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult - simpleStorageNativeDispatcherFuel - Compiler.SimpleStorageNativeWitness.nativeContract - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots) = - .error EvmYul.Yul.Exception.Revert := by - set g := simpleStorageNativeDispatcherFuel - 25 with hg_def - have hReshape : simpleStorageNativeDispatcherFuel = g + 25 := - (Nat.sub_add_cancel simpleStorageNativeDispatcherFuel_ge_25).symm - rw [hReshape] - obtain ⟨reservedNames, n0, cases', midN, hExec, hLowerCases⟩ := - simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - (g + 11) tx storage observableSlots hNoWrap - obtain ⟨storeBody', retrieveBody', hCases⟩ := - simpleStorageBuildSwitchSourceCases_lowered_shape reservedNames _ midN - cases' hLowerCases - subst hCases - obtain ⟨hStoreBody, hRetrieveBody⟩ := - simpleStorageLoweredHitCasesShape_concrete hLowerCases - subst hStoreBody - subst hRetrieveBody - set switchId := Backends.freshNativeSwitchId reservedNames n0 with hSw - let store_body : EvmYul.Yul.VarStore := - ((((∅ : EvmYul.Yul.VarStore).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)).insert - (Backends.nativeSwitchDiscrTempName switchId) - (EvmYul.UInt256.ofNat - (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (hBody : fn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((store.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let p := shared.sload (EvmYul.UInt256.ofNat 0) + let shared1 : EvmYul.SharedState .Yul := { shared with toState := p.1 } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) p.2 } + let shared3 : EvmYul.SharedState .Yul := + { shared2 with + toMachineState := + shared2.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared3 markedStore) ⟨1⟩)))) := by + intro yulTx slots markedStore shared p shared1 shared2 shared3 + have hIR := + execIRFunction_zeroParam_mstore0_sload0_return32 + fn tx state hParams hNoWrap hBody + have hProject : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared3 markedStore) ⟨1⟩)) = + { success := true, + returnValue := some p.2.toNat, + finalStorage := + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared3 markedStore), + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared3 markedStore)), + events := + state.events ++ + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared3 markedStore) } := by + have hMemory : shared.memory = ByteArray.empty := by + simp [shared, Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + simpa [yulTx, shared, p, shared1, shared2, shared3] using + projectResult_retrieveHit_eq yulTx state.storage state.events + shared markedStore hMemory + have hSlotZero : 0 ∈ slots := by + simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots] + have hp : + p.2 = state.storage (IRStorageSlot.ofNat 0) := by + have hload := + Compiler.Proofs.YulGeneration.Backends.Native.initialState_sload_materializedSlot_value + nativeContract yulTx state.storage slots 0 hSlotZero + simpa [p, shared, Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256] + using hload + have hLogs : + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared3 markedStore) = [] := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState, + shared3, shared2, shared1, p, shared, + Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.State.sload, EvmYul.State.addAccessedStorageKey, + EvmYul.Substate.addAccessedStorageKey, EvmYul.Yul.State.sharedState] + rfl + rw [hIR, hProject] + refine ⟨rfl, ?_, ?_, ?_⟩ + · simp [hp, Compiler.Proofs.IRGeneration.IRStorageWord.toNat] + · intro slot hslot + have hslot' : slot ∈ slots := by + simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots, + hslot] + have hNative := + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState_retrieveHit_initialState_materialized + nativeContract yulTx state.storage slots markedStore slot hslot' + exact hNative.symm + · rw [hLogs, List.append_nil] + +private theorem list_getD_eq_of_drop_eq_cons + {xs : List Nat} {idx arg : Nat} {rest : List Nat} + (hdrop : xs.drop idx = arg :: rest) : + xs.getD idx 0 = arg := by + have hlookup : xs[idx]? = some arg := by + simpa [hdrop, Nat.zero_add] using + (List.getElem?_drop (xs := xs) (i := idx) (j := 0)).symm + simp [List.getD, hlookup] + +/-- The direct lowered aligned-argument return halt projects to the same +observable result as the selected IR body +`mstore(0, calldataload(4 + 32*idx)); return(0, 32)`. -/ +private theorem nativeResultsMatchOn_execIRFunction_mstore0_calldataload_aligned_return32_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (idx arg : Nat) (rest : List Nat) + (hdrop : tx.args.drop idx = arg :: rest) + (hBody : fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit (4 + 32 * idx)]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((store.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert (Backends.nativeSwitchMatchedTempName switchId) (EvmYul.UInt256.ofNat 0)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1) - have hWei : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.weiValue = - (⟨0⟩ : EvmYul.Literal) := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_weiValue] - apply congrArg EvmYul.UInt256.mk - apply Fin.ext - simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256, - EvmYul.UInt256.ofNat, Fin.ofNat] using hMsgValue - have hSizeEq : - (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState.executionEnv.calldata.size = 4 := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize] - simp [hArgs] - have hTail2 := - exec_block_simpleStorageLoweredStoreCaseBodyTail2_short_revert - g (some Compiler.SimpleStorageNativeWitness.nativeContract) + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState - store_body hSizeEq - have hTail := - exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error - (g + 4) (some Compiler.SimpleStorageNativeWitness.nativeContract) + nativeContract yulTx state.storage slots).sharedState + let value := Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared2 markedStore) ⟨1⟩)))) := by + intro yulTx slots markedStore shared value shared1 shared2 + have hIR := + Compiler.Proofs.IRGeneration.execIRFunction_mstore0_calldataload_aligned_return32 + fn tx state idx hBody + have hGetD : tx.args.getD idx 0 = arg := + list_getD_eq_of_drop_eq_cons hdrop + have hProject : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared2 markedStore) ⟨1⟩)) = + { success := true, + returnValue := some value.toNat, + finalStorage := + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore), + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore)), + events := + state.events ++ + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared2 markedStore) } := by + have hMemory : shared.memory = ByteArray.empty := by + simp [shared, Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + simpa [yulTx, shared, value, shared1, shared2, + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256] using + projectResult_literalReturnHit_eq yulTx state.storage state.events + shared markedStore arg hMemory + have hValueNat : + value.toNat = arg % Compiler.Constants.evmModulus := by + simp [value, + EvmYul.UInt256.toNat, EvmYul.UInt256.ofNat, Fin.ofNat, + Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] + rfl + have hLogs : + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared2 markedStore) = [] := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState, + shared2, shared1, shared, + Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + rfl + rw [hIR, hGetD, hProject] + refine ⟨rfl, ?_, ?_, ?_⟩ + · simp [hValueNat] + · intro slot hslot + have hslot' : slot ∈ slots := by + simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots, + hslot] + have hAccountMap : + shared2.accountMap = + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState.accountMap := by + simp [shared2, shared1, shared] + have hNative := + Compiler.Proofs.YulGeneration.Backends.Native.initialState_materializedStorageSlot + nativeContract yulTx state.storage slots slot hslot' + have hNative' : + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore) + (IRStorageSlot.ofNat slot) = + state.storage (IRStorageSlot.ofNat slot) := by + simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState, + EvmYul.Yul.State.sharedState, hAccountMap] using hNative + exact hNative'.symm + · rw [hLogs, List.append_nil] + +/-- The direct lowered single-argument return halt projects to the same +observable result as the selected IR body +`mstore(0, calldataload(4)); return(0, 32)`. -/ +private theorem nativeResultsMatchOn_execIRFunction_mstore0_calldataload4_return32_markedPrefix + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (fn : IRFunction) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (arg : Nat) (rest : List Nat) + (hArgs : tx.args = arg :: rest) + (hBody : fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((store.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - observableSlots).sharedState - store_body _ hWei hTail2 - have hBodyRevert : - EvmYul.Yul.exec (g + 13) (.Block simpleStorageLoweredStoreCaseBody) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState switchId tx storage - observableSlots) = - .error EvmYul.Yul.Exception.Revert := by - exact exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error - (g + 11) _ _ _ hTail - have hReduction := hExec - rw [show (g + 11 + 14 : Nat) = (g + 4) + 2 + 19 from by omega, - show (g + 11 + 8 : Nat) = (g + 4) + 2 + 13 from by omega, - show (2 : Nat) = ([(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : - List (Nat × List EvmYul.Yul.Ast.Stmt)).length from rfl] at hReduction - have hBodyExec : ∀ pre suffix, - ([(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : - List (Nat × List EvmYul.Yul.Ast.Stmt)) = - pre ++ (0x6057361d, simpleStorageLoweredStoreCaseBody) :: suffix → - EvmYul.Yul.exec (((g + 4) + 1) + suffix.length + 7) - (.Block simpleStorageLoweredStoreCaseBody) - (some Compiler.SimpleStorageNativeWitness.nativeContract) - (simpleStorageDispatcherHitBodyInputState switchId tx storage - observableSlots) = - .error EvmYul.Yul.Exception.Revert := by - rintro pre suffix hDecomp - cases pre with - | nil => - simp only [List.nil_append, List.cons.injEq] at hDecomp - obtain ⟨_, hSuf⟩ := hDecomp - subst hSuf - simpa [simpleStorageDispatcherHitBodyInputState, store_body] using hBodyRevert - | cons _ restPre => - exfalso - simp only [List.cons_append, List.cons.injEq] at hDecomp - obtain ⟨_, hRest⟩ := hDecomp - cases restPre with - | nil => - simp only [List.nil_append, List.cons.injEq, Prod.mk.injEq] at hRest - exact absurd hRest.1.1 (by decide) - | cons _ _ => simp at hRest - have h := simpleStorageNativeContract_dispatcherExec_storeHit_error_via_reduction - (g + 4) switchId - [(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] - simpleStorageLoweredStoreCaseBody simpleStorageLoweredRetrieveCaseBody - tx storage observableSlots EvmYul.Yul.Exception.Revert - hSelector rfl hBodyExec hReduction - have hLen : - ([(0x6057361d, simpleStorageLoweredStoreCaseBody), - (0x2e64cec1, simpleStorageLoweredRetrieveCaseBody)] : - List (Nat × List EvmYul.Yul.Ast.Stmt)).length = 2 := rfl - rw [hLen, show (g + 4) + 2 + 19 = g + 25 from by omega] at h - exact h + nativeContract yulTx state.storage slots).sharedState + let value := Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + nativeResultsMatchOn observableSlots + (execIRFunction fn tx.args (applyIRTransactionContext tx state)) + (.ok + (Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared2 markedStore) ⟨1⟩)))) := by + intro yulTx slots markedStore shared value shared1 shared2 + have hIR := + Compiler.Proofs.IRGeneration.execIRFunction_mstore0_calldataload4_return32_of_args_cons + fn tx state arg rest hBody hArgs + have hProject : + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt + (EvmYul.Yul.State.Ok shared2 markedStore) ⟨1⟩)) = + { success := true, + returnValue := some value.toNat, + finalStorage := + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore), + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore)), + events := + state.events ++ + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared2 markedStore) } := by + have hMemory : shared.memory = ByteArray.empty := by + simp [shared, Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + simpa [yulTx, shared, value, shared1, shared2, + Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256] using + projectResult_literalReturnHit_eq yulTx state.storage state.events + shared markedStore arg hMemory + have hValueNat : + value.toNat = arg % Compiler.Constants.evmModulus := by + simp [value, + EvmYul.UInt256.toNat, EvmYul.UInt256.ofNat, Fin.ofNat, + Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] + rfl + have hLogs : + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState + (EvmYul.Yul.State.Ok shared2 markedStore) = [] := by + simp [Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState, + shared2, shared1, shared, + Compiler.Proofs.YulGeneration.Backends.Native.initialState, + Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, + YulState.initial, EvmYul.Yul.State.sharedState] + rfl + rw [hIR, hProject] + refine ⟨rfl, ?_, ?_, ?_⟩ + · simp [hValueNat] + · intro slot hslot + have hslot' : slot ∈ slots := by + simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots, + hslot] + have hAccountMap : + shared2.accountMap = + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState.accountMap := by + simp [shared2, shared1, shared] + have hNative := + Compiler.Proofs.YulGeneration.Backends.Native.initialState_materializedStorageSlot + nativeContract yulTx state.storage slots slot hslot' + have hNative' : + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState + yulTx (EvmYul.Yul.State.Ok shared2 markedStore) + (IRStorageSlot.ofNat slot) = + state.storage (IRStorageSlot.ofNat slot) := by + simpa [Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState, + EvmYul.Yul.State.sharedState, hAccountMap] using hNative + exact hNative'.symm + · rw [hLogs, List.append_nil] + +/-- Build the direct selected-user-body halt bridge for the generated +`retrieve()` body shape. -/ +private theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_sload0_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hRetrieveBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody := hRetrieveBody fn hFind + have hLowerConcrete : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart + ([Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] : List Yul.YulStmt) = + .ok (simpleStorageLoweredRetrieveCaseBodyTail3, userBodyStart) := by + simp [simpleStorageLoweredRetrieveCaseBodyTail3, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_expr, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + have hLowerPair : + (bodyNative, bodyEnd) = (simpleStorageLoweredRetrieveCaseBodyTail3, userBodyStart) := by + rw [hBody, hLowerConcrete] at hUserBodyLower + simpa using hUserBodyLower.symm + rcases hLowerPair with ⟨rfl, rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let p := shared.sload (EvmYul.UInt256.ofNat 0) + let shared1 : EvmYul.SharedState .Yul := { shared with toState := p.1 } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) p.2 } + let shared3 : EvmYul.SharedState .Yul := + { shared2 with + toMachineState := + shared2.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + let haltState := EvmYul.Yul.State.Ok shared3 markedStore + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState ⟨1⟩)) + refine ⟨haltState, ⟨1⟩, nativeYul, ?_, rfl, ?_⟩ + · intro _pre suffix + have hExec := + exec_block_simpleStorageLoweredRetrieveCaseBodyTail3_closed + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + (some nativeContract) shared markedStore + change + EvmYul.Yul.exec + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10) + (.Block simpleStorageLoweredRetrieveCaseBodyTail3) + (some nativeContract) (EvmYul.Yul.State.Ok shared markedStore) = + .error (EvmYul.Yul.Exception.YulHalt haltState ⟨1⟩) + rw [show + nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10 = + nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1 + 9 by omega] + simpa [shared, p, shared1, shared2, shared3, haltState] using hExec + · simpa [switchId, yulTx, slots, markedStore, shared, p, shared1, shared2, + shared3, haltState, nativeYul] using + (nativeResultsMatchOn_execIRFunction_mstore0_sload0_return32_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + hBody) + +private theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_sload0_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hParams : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params = []) + (hRetrieveBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody := hRetrieveBody fn hFind + have hFnParams := hParams fn hFind + have hLowerConcrete : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart + (Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] : List Yul.YulStmt) = + .ok (loweredZeroParamSload0ReturnCaseBody, userBodyStart) := by + simp [loweredZeroParamSload0ReturnCaseBody, + simpleStorageLoweredRetrieveCaseBodyTail3, + Compiler.CompilationModel.genParamLoads, + Compiler.CompilationModel.genParamLoadsFrom, + Compiler.CompilationModel.genParamLoadBodyFrom, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_expr, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_if, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + have hLowerPair : + (bodyNative, bodyEnd) = + (loweredZeroParamSload0ReturnCaseBody, userBodyStart) := by + rw [hBody, hLowerConcrete] at hUserBodyLower + simpa using hUserBodyLower.symm + rcases hLowerPair with ⟨rfl, rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let p := shared.sload (EvmYul.UInt256.ofNat 0) + let shared1 : EvmYul.SharedState .Yul := { shared with toState := p.1 } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) p.2 } + let shared3 : EvmYul.SharedState .Yul := + { shared2 with + toMachineState := + shared2.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + let haltState := EvmYul.Yul.State.Ok shared3 markedStore + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState ⟨1⟩)) + refine ⟨haltState, ⟨1⟩, nativeYul, ?_, rfl, ?_⟩ + · intro _pre suffix + have hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size := by + simpa [shared, yulTx, + Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_size] + using hNoWrap + have hGe : 4 ≤ shared.executionEnv.calldata.size := by + simp [shared, yulTx, + Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_size] + have hExec := + exec_block_loweredZeroParamSload0ReturnCaseBody_closed + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length) + (some nativeContract) shared markedStore hSize hGe + simpa [shared, p, shared1, shared2, shared3, haltState] using hExec + · simpa [switchId, yulTx, slots, markedStore, shared, p, shared1, shared2, + shared3, haltState, nativeYul] using + (nativeResultsMatchOn_execIRFunction_zeroParam_mstore0_sload0_return32_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + hFnParams hNoWrap hBody) + +private theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_lit_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (value : Nat) + (hValueRange : value < EvmYul.UInt256.size) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody := hReturnBody fn hFind + have hLowerConcrete : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart + ([Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] : List Yul.YulStmt) = + .ok (loweredLiteralReturnCaseBodyTail value, userBodyStart) := by + simp [loweredLiteralReturnCaseBodyTail, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_expr, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + have hLowerPair : + (bodyNative, bodyEnd) = (loweredLiteralReturnCaseBodyTail value, userBodyStart) := by + rw [hBody, hLowerConcrete] at hUserBodyLower + simpa using hUserBodyLower.symm + rcases hLowerPair with ⟨rfl, rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat value) } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + let haltState := EvmYul.Yul.State.Ok shared2 markedStore + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState ⟨1⟩)) + refine ⟨haltState, ⟨1⟩, nativeYul, ?_, rfl, ?_⟩ + · intro _pre suffix + have hExec := + exec_block_loweredLiteralReturnCaseBodyTail_closed + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 2) + (some nativeContract) shared markedStore value + rw [show + nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10 = + nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 2 + 8 by omega] + simpa [shared, shared1, shared2, haltState] using hExec + · simpa [switchId, yulTx, slots, markedStore, shared, shared1, shared2, + haltState, nativeYul] using + (nativeResultsMatchOn_execIRFunction_mstore0_lit_return32_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + value hValueRange hBody) + +private theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_lit_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (value : Nat) + (hValueRange : value < EvmYul.UInt256.size) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hParams : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params = []) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody := hReturnBody fn hFind + have hFnParams := hParams fn hFind + have hLowerConcrete : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart + (Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] : List Yul.YulStmt) = + .ok (loweredZeroParamLiteralReturnCaseBody value, userBodyStart) := by + simp [loweredZeroParamLiteralReturnCaseBody, loweredLiteralReturnCaseBodyTail, + Compiler.CompilationModel.genParamLoads, + Compiler.CompilationModel.genParamLoadsFrom, + Compiler.CompilationModel.genParamLoadBodyFrom, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_expr, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_if, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + have hLowerPair : + (bodyNative, bodyEnd) = + (loweredZeroParamLiteralReturnCaseBody value, userBodyStart) := by + rw [hBody, hLowerConcrete] at hUserBodyLower + simpa using hUserBodyLower.symm + rcases hLowerPair with ⟨rfl, rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat value) } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + let haltState := EvmYul.Yul.State.Ok shared2 markedStore + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState ⟨1⟩)) + refine ⟨haltState, ⟨1⟩, nativeYul, ?_, rfl, ?_⟩ + · intro _pre suffix + have hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size := by + simpa [shared, yulTx, + Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_size] + using hNoWrap + have hGe : 4 ≤ shared.executionEnv.calldata.size := by + simp [shared, yulTx, + Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_size] + have hExec := + exec_block_loweredZeroParamLiteralReturnCaseBody_closed + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length) + (some nativeContract) shared markedStore value hSize hGe + simpa [shared, shared1, shared2, haltState] using hExec + · simpa [switchId, yulTx, slots, markedStore, shared, shared1, shared2, + haltState, nativeYul] using + (nativeResultsMatchOn_execIRFunction_zeroParam_mstore0_lit_return32_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + value hValueRange hFnParams hNoWrap hBody) -/-- Projected native storage after the generated `store(uint256)` body agrees -with the IR setter update on every materialized slot. The native zero-write -case erases slot zero from the finite EVM map; projected lookup still agrees -with IR storage because missing native storage reads as the zero word. -/ -theorem projectStorageFromState_storeHit_initialState_materialized - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (slots : List Nat) (store : EvmYul.Yul.VarStore) - (arg slot : Nat) - (hSlot : slot ∈ slots) : - let initialWithStore : EvmYul.Yul.State := - .Ok (Compiler.Proofs.YulGeneration.Backends.Native.initialState - Compiler.SimpleStorageNativeWitness.nativeContract tx storage - slots).sharedState store - let withValue := initialWithStore.insert "value" - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg) - let finalState := withValue.setState - (withValue.toState.sstore (EvmYul.UInt256.ofNat 0) - (Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg)) - Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState tx - finalState (IRStorageSlot.ofNat slot) = - (Compiler.Proofs.abstractStoreStorageOrMapping storage 0 arg) - (IRStorageSlot.ofNat slot) := by - intro initialWithStore withValue finalState - simp only [Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState, - Compiler.Proofs.YulGeneration.Backends.StateBridge.extractStorage, - finalState, withValue, initialWithStore, - EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.Yul.State.insert, - EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, - Compiler.Proofs.YulGeneration.Backends.Native.initialState, - Compiler.Proofs.YulGeneration.Backends.StateBridge.toSharedState, - YulState.initial, - Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256] - simp only [Option.option, - Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - by_cases hValueZero : - (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = true - · rw [hValueZero] - simp only [ite_true, IRStorageSlot.toUInt256, IRStorageSlot.ofNat] - have hArgZeroUInt : - EvmYul.UInt256.ofNat arg = (⟨0⟩ : EvmYul.UInt256) := by - cases hArg : EvmYul.UInt256.ofNat arg with - | mk v => - rw [hArg] at hValueZero - change (v == (0 : Fin EvmYul.UInt256.size)) = true at hValueZero - have hv : v = (0 : Fin EvmYul.UInt256.size) := - of_decide_eq_true hValueZero - subst hv - rfl - have hArgZero : IRStorageWord.ofNat arg = (0 : IRStorageWord) := by - simpa [Compiler.Proofs.IRGeneration.IRStorageWord.ofNat] using hArgZeroUInt - by_cases hKey : - compare (EvmYul.UInt256.ofNat slot) (EvmYul.UInt256.ofNat 0) = - Ordering.eq - · have hSlotEq : - IRStorageSlot.ofNat slot = IRStorageSlot.ofNat 0 := by - have hUInt : - EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := - Compiler.Proofs.YulGeneration.Backends.StateBridge.UInt256_eq_of_compare_eq - hKey - simpa [IRStorageSlot.ofNat] using hUInt - have hUInt : - EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := by - simpa [IRStorageSlot.ofNat] using hSlotEq - have hErase : - (Batteries.RBMap.erase - (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage - storage slots) - (EvmYul.UInt256.ofNat 0)).find? (EvmYul.UInt256.ofNat slot) = - none := by - simpa [hUInt] using - (Batteries.RBMap.find?_erase_self - (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage - storage slots) - (EvmYul.UInt256.ofNat 0)) - rw [hErase, hUInt] - simp only [Compiler.Proofs.abstractStoreStorageOrMapping, - Compiler.Proofs.IRGeneration.IRStorageWord.ofNat, IRStorageSlot.ofNat] - simp only [if_true] - rw [hArgZeroUInt] - rfl - · have hErase : - (Batteries.RBMap.erase - (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage - storage slots) - (EvmYul.UInt256.ofNat 0)).find? (EvmYul.UInt256.ofNat slot) = - (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage - storage slots).find? (EvmYul.UInt256.ofNat slot) := by - exact Batteries.RBMap.find?_erase_of_ne _ hKey - have hLookup := - Compiler.Proofs.YulGeneration.Backends.StateBridge.storageLookup_projectStorage_projected - storage slots slot hSlot - have hLookup' : - (match - (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage - storage slots).find? (EvmYul.UInt256.ofNat slot) with - | some val => val - | none => (⟨0⟩ : EvmYul.UInt256)) = - storage (IRStorageSlot.ofNat slot) := by - simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.storageLookup, - Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256] - using hLookup - rw [hErase] - have hSlotNe : - IRStorageSlot.ofNat slot ≠ IRStorageSlot.ofNat 0 := by - intro hEq - apply hKey - have hUIntEq : - EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := by - simpa [IRStorageSlot.ofNat] using hEq - rw [hUIntEq] - exact Std.ReflCmp.compare_self - have hSlotNe' : - EvmYul.UInt256.ofNat slot ≠ IRStorageSlot.ofNat 0 := by - simpa [IRStorageSlot.ofNat] using hSlotNe - have hSlotNeUInt : - EvmYul.UInt256.ofNat slot ≠ EvmYul.UInt256.ofNat 0 := by - intro hEq - exact hSlotNe' (by simpa [IRStorageSlot.ofNat] using hEq) - simpa [Compiler.Proofs.abstractStoreStorageOrMapping, IRStorageSlot.ofNat, - hSlotNeUInt] using hLookup' - · have hValueNonzero : - (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = - false := by - cases h : - (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) <;> - simp [h] at hValueZero ⊢ - rw [hValueNonzero] - simp only [Bool.false_eq_true, ite_false, IRStorageSlot.toUInt256, - IRStorageSlot.ofNat] - by_cases hKey : - compare (EvmYul.UInt256.ofNat slot) (EvmYul.UInt256.ofNat 0) = - Ordering.eq - · have hSlotEq : - IRStorageSlot.ofNat slot = IRStorageSlot.ofNat 0 := by - have hUInt : - EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := - Compiler.Proofs.YulGeneration.Backends.StateBridge.UInt256_eq_of_compare_eq - hKey - simpa [IRStorageSlot.ofNat] using hUInt - have hUInt : - EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := by - simpa [IRStorageSlot.ofNat] using hSlotEq - rw [Batteries.RBMap.find?_insert_of_eq _ hKey] - rw [hUInt] - simp [Compiler.Proofs.abstractStoreStorageOrMapping, - Compiler.Proofs.IRGeneration.IRStorageWord.ofNat, IRStorageSlot.ofNat] - · rw [Batteries.RBMap.find?_insert_of_ne _ hKey] - have hLookup := - Compiler.Proofs.YulGeneration.Backends.StateBridge.storageLookup_projectStorage_projected - storage slots slot hSlot - have hLookup' : - (match - (Compiler.Proofs.YulGeneration.Backends.StateBridge.projectStorage - storage slots).find? (EvmYul.UInt256.ofNat slot) with - | some val => val - | none => (⟨0⟩ : EvmYul.UInt256)) = - storage (IRStorageSlot.ofNat slot) := by - simpa [Compiler.Proofs.YulGeneration.Backends.StateBridge.storageLookup, - Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256] - using hLookup - have hSlotNe : - IRStorageSlot.ofNat slot ≠ IRStorageSlot.ofNat 0 := by - intro hEq - apply hKey - have hUIntEq : - EvmYul.UInt256.ofNat slot = EvmYul.UInt256.ofNat 0 := by - simpa [IRStorageSlot.ofNat] using hEq - rw [hUIntEq] - exact Std.ReflCmp.compare_self - have hSlotNe' : - EvmYul.UInt256.ofNat slot ≠ IRStorageSlot.ofNat 0 := by - simpa [IRStorageSlot.ofNat] using hSlotNe - have hSlotNeUInt : - EvmYul.UInt256.ofNat slot ≠ EvmYul.UInt256.ofNat 0 := by - intro hEq - exact hSlotNe' (by simpa [IRStorageSlot.ofNat] using hEq) - simpa [Compiler.Proofs.abstractStoreStorageOrMapping, IRStorageSlot.ofNat, - hSlotNeUInt] using hLookup' +private theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload4_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots := by + rcases hArgsCons with ⟨arg, rest, hArgs⟩ + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody := hReturnBody fn hFind + have hLowerConcrete : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart + ([Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] : List Yul.YulStmt) = + .ok (loweredCalldataload4ReturnCaseBodyTail, userBodyStart) := by + simp [loweredCalldataload4ReturnCaseBodyTail, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_expr, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + have hLowerPair : + (bodyNative, bodyEnd) = (loweredCalldataload4ReturnCaseBodyTail, userBodyStart) := by + rw [hBody, hLowerConcrete] at hUserBodyLower + simpa using hUserBodyLower.symm + rcases hLowerPair with ⟨rfl, rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let value := Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + let haltState := EvmYul.Yul.State.Ok shared2 markedStore + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState ⟨1⟩)) + refine ⟨haltState, ⟨1⟩, nativeYul, ?_, rfl, ?_⟩ + · intro _pre suffix + have hWord : + shared.calldataload (EvmYul.UInt256.ofNat 4) = value := by + simpa [shared, value, EvmYul.Yul.State.toState] using + Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataload4_arg0_word + nativeContract yulTx state.storage slots arg rest hArgs + have hExec := + exec_block_loweredCalldataload4ReturnCaseBodyTail_closed + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + (some nativeContract) shared markedStore arg hWord + rw [show + nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10 = + nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1 + 9 by omega] + simpa [shared, value, shared1, shared2, haltState] using hExec + · simpa [switchId, yulTx, slots, markedStore, shared, value, shared1, shared2, + haltState, nativeYul] using + (nativeResultsMatchOn_execIRFunction_mstore0_calldataload4_return32_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + arg rest hArgs hBody) + +private theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload_aligned_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (idx arg : Nat) + (rest : List Nat) + (hArgDrop : tx.args.drop idx = arg :: rest) + (hOffset64 : 4 + 32 * idx < 2 ^ 64) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit (4 + 32 * idx)]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state + observableSlots := by + intro nativeContract fn reservedNames n0 cases' bodyNative bodyEnd + userBodyStart _hLowerRuntime hFind hUserBodyLower _hguards _hArgs + have hBody := hReturnBody fn hFind + have hLowerConcrete : + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds + reservedNames userBodyStart + ([Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit (4 + 32 * idx)]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] : List Yul.YulStmt) = + .ok (loweredCalldataloadReturnCaseBodyTail idx, userBodyStart) := by + simp [loweredCalldataloadReturnCaseBodyTail, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_cons, + Compiler.Proofs.YulGeneration.Backends.lowerStmtsNativeWithSwitchIds_nil, + Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_expr, + Bind.bind, Except.bind, Pure.pure, Except.pure, List.append_nil] + have hLowerPair : + (bodyNative, bodyEnd) = + (loweredCalldataloadReturnCaseBodyTail idx, userBodyStart) := by + rw [hBody, hLowerConcrete] at hUserBodyLower + simpa using hUserBodyLower.symm + rcases hLowerPair with ⟨rfl, rfl⟩ + let switchId := + Compiler.Proofs.YulGeneration.Backends.freshNativeSwitchId reservedNames n0 + let yulTx := YulTransaction.ofIR tx + let slots := + Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots + (Compiler.runtimeCode irContract) observableSlots + let markedStore := + (((Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore.insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (yulTx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + let shared := + (Compiler.Proofs.YulGeneration.Backends.Native.initialState + nativeContract yulTx state.storage slots).sharedState + let value := Compiler.Proofs.YulGeneration.Backends.StateBridge.natToUInt256 arg + let shared1 : EvmYul.SharedState .Yul := + { shared with + toMachineState := + shared.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + let haltState := EvmYul.Yul.State.Ok shared2 markedStore + let nativeYul := + Compiler.Proofs.YulGeneration.Backends.Native.projectResult + yulTx state.storage state.events + (.error (EvmYul.Yul.Exception.YulHalt haltState ⟨1⟩)) + refine ⟨haltState, ⟨1⟩, nativeYul, ?_, rfl, ?_⟩ + · intro _pre suffix + have hWord : + shared.calldataload (EvmYul.UInt256.ofNat (4 + 32 * idx)) = value := by + simpa [shared, value, yulTx, EvmYul.Yul.State.toState] using + Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataload_aligned_arg_word + nativeContract yulTx state.storage slots idx arg rest hArgDrop hOffset64 + have hExec := + exec_block_loweredCalldataloadReturnCaseBodyTail_closed + (nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1) + (some nativeContract) shared markedStore idx arg hWord + rw [show + nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 10 = + nativeGeneratedSelectorHitUserBodyFuel irContract fn cases' + + suffix.length + 1 + 9 by omega] + simpa [shared, value, shared1, shared2, haltState] using hExec + · simpa [switchId, yulTx, slots, markedStore, shared, value, shared1, shared2, + haltState, nativeYul] using + (nativeResultsMatchOn_execIRFunction_mstore0_calldataload_aligned_return32_markedPrefix + irContract tx state observableSlots nativeContract fn switchId + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchHasSelectorStore + idx arg rest hArgDrop hBody) + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_sload0_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hRetrieveBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt irContract tx state + observableSlots + (NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_sload0_return32 + irContract tx state observableSlots hRetrieveBody) + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_sload0_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hParams : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params = []) + (hRetrieveBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt irContract tx state + observableSlots + (NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_sload0_return32 + irContract tx state observableSlots hNoWrap hParams hRetrieveBody) + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_lit_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (value : Nat) + (hValueRange : value < EvmYul.UInt256.size) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt irContract tx state + observableSlots + (NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_lit_return32 + irContract tx state observableSlots value hValueRange hReturnBody) + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_lit_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (value : Nat) + (hValueRange : value < EvmYul.UInt256.size) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hParams : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params = []) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt irContract tx state + observableSlots + (NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_lit_return32 + irContract tx state observableSlots value hValueRange hNoWrap + hParams hReturnBody) + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload4_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt irContract tx state + observableSlots + (NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload4_return32 + irContract tx state observableSlots hArgsCons hReturnBody) + +private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload_aligned_return32 + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (idx arg : Nat) + (rest : List Nat) + (hArgDrop : tx.args.drop idx = arg :: rest) + (hOffset64 : 4 + 32 * idx < 2 ^ 64) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit (4 + 32 * idx)]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + NativeGeneratedSelectedUserBodyResultBridgeAtFuel irContract tx state + observableSlots := + NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt irContract tx state + observableSlots + (NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload_aligned_return32 + irContract tx state observableSlots idx arg rest hArgDrop hOffset64 hReturnBody) + +/-- Closed generated `callDispatcher` theorem for selected retrieve-body success. + +This mirrors the store-body closed theorem through the unified selected-body +result boundary, discharging the selected user-body halt bridge from the +concrete native `mstore(0, sload(0)); return(0, 32)` proof above. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_sload0_return32 + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hRetrieveBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_sload0_return32 + irContract tx state observableSlots hRetrieveBody) + hThreshold -/-- Closed-form evaluation of `projectResult` on the retrieve-hit halt error -produced by the lowered SimpleStorage retrieve body. The halt state is built -by chaining `sload(0)` (toState override), `mstore(0, _)` (toMachineState -override), and `evmReturn(0, 32)` (toMachineState override) starting from a -shared state with empty memory. The native projected return value is the -`Nat`-normalized form of the loaded slot-zero word; storage and logs are -read off the halt's `sharedState` directly. -/ -theorem projectResult_retrieveHit_eq - (tx : YulTransaction) (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hMemory : shared.memory = ByteArray.empty) : - let p := shared.sload (EvmYul.UInt256.ofNat 0) - let shared1 : EvmYul.SharedState .Yul := { shared with toState := p.1 } - let shared2 : EvmYul.SharedState .Yul := - { shared1 with - toMachineState := - shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) p.2 } - let shared3 : EvmYul.SharedState .Yul := - { shared2 with - toMachineState := - shared2.toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } - Compiler.Proofs.YulGeneration.Backends.Native.projectResult - tx initialStorage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt - (EvmYul.Yul.State.Ok shared3 store) ⟨1⟩)) = - { success := true, - returnValue := some p.2.toNat, - finalStorage := - Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState - tx (EvmYul.Yul.State.Ok shared3 store), - finalMappings := - Compiler.Proofs.storageAsMappings - (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState - tx (EvmYul.Yul.State.Ok shared3 store)), - events := - initialEvents ++ - Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState - (EvmYul.Yul.State.Ok shared3 store) } := by - intro p shared1 shared2 shared3 - -- shared1 inherits memory from shared because only `toState` was overridden. - have hMemory1 : shared1.memory = ByteArray.empty := hMemory - -- The harness helpers describe the result via `setMachineState` chains; - -- those equal the structural overrides used in `shared3`. - have hSize : - (EvmYul.Yul.State.Ok shared3 store).sharedState.H_return.size = 32 := by - have h := Compiler.Proofs.YulGeneration.Backends.Native.mstore0_then_return32_hReturn_size - shared1 store p.2 - simpa [shared3, shared2, EvmYul.Yul.State.setMachineState, - EvmYul.Yul.State.toMachineState, EvmYul.Yul.State.sharedState] using h - have hH_return : - (EvmYul.Yul.State.Ok shared3 store).sharedState.H_return = p.2.toByteArray := by - have h := - Compiler.Proofs.YulGeneration.Backends.Native.mstore0_then_return32_emptyMemory_hReturn_eq_toByteArray - shared1 store p.2 hMemory1 - simpa [shared3, shared2, EvmYul.Yul.State.setMachineState, - EvmYul.Yul.State.toMachineState, EvmYul.Yul.State.sharedState] using h - have hHaltNotZero : (⟨1⟩ : EvmYul.Yul.Ast.Literal) ≠ ⟨0⟩ := by - intro h - norm_num [EvmYul.UInt256.size] at h - have hReturnValue : - Compiler.Proofs.YulGeneration.Backends.Native.projectHaltReturn - (EvmYul.Yul.State.Ok shared3 store) ⟨1⟩ = some p.2.toNat := by - rw [Compiler.Proofs.YulGeneration.Backends.Native.projectHaltReturn_32ByteReturn - (EvmYul.Yul.State.Ok shared3 store) ⟨1⟩ hHaltNotZero hSize] - rw [hH_return, - Compiler.Proofs.YulGeneration.Backends.Native.byteArrayWord_uint256_toByteArray] - simp only [Compiler.Proofs.YulGeneration.Backends.Native.projectResult, - hReturnValue] +/-- Closed generated `callDispatcher` theorem for a selected generated +zero-parameter storage-return body. The body includes `genParamLoads []` +before `mstore(0, sload(0)); return(0, 32)`. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_sload0_return32 + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hParams : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params = []) + (hRetrieveBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_sload0_return32 + irContract tx state observableSlots hNoWrap hParams hRetrieveBody) + hThreshold + +/-- Closed generated `callDispatcher` theorem for a selected literal-return +body `mstore(0, value); return(0, 32)`. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_lit_return32 + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (value : Nat) + (hValueRange : value < EvmYul.UInt256.size) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_lit_return32 + irContract tx state observableSlots value hValueRange hReturnBody) + hThreshold + +private theorem selectedCompiledFunction_zeroParam_lit_return32_shape_of_forall₂ + (fields : List CompilationModel.Field) + (events : List CompilationModel.EventDef) + (errors : List CompilationModel.ErrorDef) + (tx : IRTransaction) + (value : Nat) + {pairs : List (CompilationModel.FunctionSpec × Nat)} + {irFns : List IRFunction} + (hcompiled : + List.Forall₂ + (fun entry irFn => + CompilationModel.compileFunctionSpec fields events errors + [] entry.2 entry.1 = Except.ok irFn) + pairs irFns) + (hSourceParams : + ∀ entry, entry ∈ pairs → entry.2 = tx.functionSelector → + entry.1.params = []) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ pairs → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList fields events errors .calldata + [] false (entry.1.params.map (·.name)) [] entry.1.body = + Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) + (irFn : IRFunction) + (hFind : + irFns.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn) : + irFn.params = [] ∧ + irFn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] := by + induction hcompiled with + | nil => + simp at hFind + | @cons entry headIr tailPairs tailIr hhead htail ih => + by_cases hSelector : headIr.selector = tx.functionSelector + · simp [hSelector] at hFind + rcases hFind with rfl + have hEntrySelector : entry.2 = tx.functionSelector := by + have hSel := + Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_selector + fields events errors entry.2 entry.1 headIr hhead + simpa [hSelector] using hSel.symm + rcases + Compiler.Proofs.IRGeneration.FunctionShape.compileFunctionSpec_ok_components + fields events errors entry.2 entry.1 headIr hhead with + ⟨returns, bodyStmts, _hvalidate, _hreturns, hbody, hirFn⟩ + have hEntryMem : entry ∈ entry :: tailPairs := by simp + have hSpecParams : entry.1.params = [] := + hSourceParams entry hEntryMem hEntrySelector + have hBodyStmts : + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] := + hSourceBody entry bodyStmts hEntryMem hEntrySelector hbody + constructor + · rw [hirFn] + simp [Compiler.Proofs.IRGeneration.FunctionShape.compiledFunctionIR, + hSpecParams] + · rw [hirFn] + simp [Compiler.Proofs.IRGeneration.FunctionShape.compiledFunctionIR, + hSpecParams, hBodyStmts] + · have hFindTail : + tailIr.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn := by + simpa [hSelector] using hFind + exact ih + (fun entry' hMem => + hSourceParams entry' (by simp [hMem])) + (fun entry' bodyStmts hMem => + hSourceBody entry' bodyStmts (by simp [hMem])) + hFindTail + +private theorem selectedGeneratedFunction_zeroParam_lit_return32_shape_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (value : Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSourceParams : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + entry.1.params = []) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .calldata [] false (entry.1.params.map (·.name)) [] + entry.1.body = Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) + (irFn : IRFunction) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn) : + irFn.params = [] ∧ + irFn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] := by + have hcompiled := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions + spec selectors hSupported irContract hcompile + exact + selectedCompiledFunction_zeroParam_lit_return32_shape_of_forall₂ + spec.fields spec.events spec.errors tx value hcompiled hSourceParams + hSourceBody irFn hFind + +private theorem selectedCompiledFunction_zeroParam_sload0_return32_shape_of_forall₂ + (fields : List CompilationModel.Field) + (events : List CompilationModel.EventDef) + (errors : List CompilationModel.ErrorDef) + (tx : IRTransaction) + {pairs : List (CompilationModel.FunctionSpec × Nat)} + {irFns : List IRFunction} + (hcompiled : + List.Forall₂ + (fun entry irFn => + CompilationModel.compileFunctionSpec fields events errors + [] entry.2 entry.1 = Except.ok irFn) + pairs irFns) + (hSourceParams : + ∀ entry, entry ∈ pairs → entry.2 = tx.functionSelector → + entry.1.params = []) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ pairs → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList fields events errors .calldata + [] false (entry.1.params.map (·.name)) [] entry.1.body = + Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) + (irFn : IRFunction) + (hFind : + irFns.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn) : + irFn.params = [] ∧ + irFn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] := by + induction hcompiled with + | nil => + simp at hFind + | @cons entry headIr tailPairs tailIr hhead htail ih => + by_cases hSelector : headIr.selector = tx.functionSelector + · simp [hSelector] at hFind + rcases hFind with rfl + have hEntrySelector : entry.2 = tx.functionSelector := by + have hSel := + Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_selector + fields events errors entry.2 entry.1 headIr hhead + simpa [hSelector] using hSel.symm + rcases + Compiler.Proofs.IRGeneration.FunctionShape.compileFunctionSpec_ok_components + fields events errors entry.2 entry.1 headIr hhead with + ⟨returns, bodyStmts, _hvalidate, _hreturns, hbody, hirFn⟩ + have hEntryMem : entry ∈ entry :: tailPairs := by simp + have hSpecParams : entry.1.params = [] := + hSourceParams entry hEntryMem hEntrySelector + have hBodyStmts : + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] := + hSourceBody entry bodyStmts hEntryMem hEntrySelector hbody + constructor + · rw [hirFn] + simp [Compiler.Proofs.IRGeneration.FunctionShape.compiledFunctionIR, + hSpecParams] + · rw [hirFn] + simp [Compiler.Proofs.IRGeneration.FunctionShape.compiledFunctionIR, + hSpecParams, hBodyStmts] + · have hFindTail : + tailIr.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn := by + simpa [hSelector] using hFind + exact ih + (fun entry' hMem => + hSourceParams entry' (by simp [hMem])) + (fun entry' bodyStmts hMem => + hSourceBody entry' bodyStmts (by simp [hMem])) + hFindTail + +private theorem selectedGeneratedFunction_zeroParam_sload0_return32_shape_of_compile_ok_supported + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSourceParams : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + entry.1.params = []) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .calldata [] false (entry.1.params.map (·.name)) [] + entry.1.body = Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) + (irFn : IRFunction) + (hFind : + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some irFn) : + irFn.params = [] ∧ + irFn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])] := by + have hcompiled := + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions + spec selectors hSupported irContract hcompile + exact + selectedCompiledFunction_zeroParam_sload0_return32_shape_of_forall₂ + spec.fields spec.events spec.errors tx hcompiled hSourceParams + hSourceBody irFn hFind + +/-- Closed generated `callDispatcher` theorem for a selected generated +zero-parameter literal-return body. The body includes `genParamLoads []` +before `mstore(0, value); return(0, 32)`. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_lit_return32 + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (value : Nat) + (hValueRange : value < EvmYul.UInt256.size) + (hParams : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.params = []) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = + Compiler.CompilationModel.genParamLoads [] ++ + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_lit_return32 + irContract tx state observableSlots value hValueRange hNoWrap + hParams hReturnBody) + hThreshold + +/-- Source-shape variant of the closed generated `callDispatcher` theorem for +zero-parameter literal-return bodies. It derives the selected IR function +params/body shape from `compileFunctionSpec` instead of requiring direct +premises over `irContract.functions.find?`. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_lit_return32 + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (value : Nat) + (hValueRange : value < EvmYul.UInt256.size) + (hSourceParams : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + entry.1.params = []) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .calldata [] false (entry.1.params.map (·.name)) [] + entry.1.body = Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_lit_return32 + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold value hValueRange + (fun fn hFind => + (selectedGeneratedFunction_zeroParam_lit_return32_shape_of_compile_ok_supported + spec selectors hSupported irContract tx value hcompile hSourceParams + hSourceBody fn hFind).1) + (fun fn hFind => + (selectedGeneratedFunction_zeroParam_lit_return32_shape_of_compile_ok_supported + spec selectors hSupported irContract tx value hcompile hSourceParams + hSourceBody fn hFind).2) + +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_sload0_return32 + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hSourceParams : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + entry.1.params = []) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .calldata [] false (entry.1.params.map (·.name)) [] + entry.1.body = Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_sload0_return32 + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap hThreshold + (fun fn hFind => + (selectedGeneratedFunction_zeroParam_sload0_return32_shape_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile hSourceParams + hSourceBody fn hFind).1) + (fun fn hFind => + (selectedGeneratedFunction_zeroParam_sload0_return32_shape_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile hSourceParams + hSourceBody fn hFind).2) + +private theorem compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher_source_zeroParam_lit_return32 + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (value : Nat) + (hValueRange : value < EvmYul.UInt256.size) + (hSourceParams : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + entry.1.params = []) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .calldata [] false (entry.1.params.map (·.name)) [] + entry.1.body = Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit value]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics spec selectors hSupported tx + initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots nativeContract) := by + rcases + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_lit_return32 + spec selectors hSupported irContract tx + (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots hcompile hSelectorRange hSelectorsRange hNoWrap + (fun fn hFind => + generatedFunctionCalldataThreshold_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile fn hFind) + value hValueRange hSourceParams hSourceBody with + ⟨nativeContract, hLower, hMatch⟩ + exact + ⟨nativeContract, hLower, + compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match + spec selectors hSupported irContract tx initialWorld observableSlots + nativeContract htxNormalized hcalldataSizeFits hcompile hMatch⟩ + +private theorem compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher_source_zeroParam_sload0_return32 + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (initialWorld : Verity.ContractState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (htxNormalized : Function.TxContextNormalized tx) + (hcalldataSizeFits : Function.TxCalldataSizeFitsEvm tx) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSourceParams : + ∀ entry, entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + entry.1.params = []) + (hSourceBody : + ∀ entry bodyStmts, + entry ∈ SourceSemantics.selectorFunctionPairs spec selectors → + entry.2 = tx.functionSelector → + CompilationModel.compileStmtList spec.fields spec.events spec.errors + .calldata [] false (entry.1.params.map (·.name)) [] + entry.1.body = Except.ok bodyStmts → + bodyStmts = + [Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, Yul.YulExpr.call "sload" [Yul.YulExpr.lit 0]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + sourceResultMatchesNativeOn observableSlots + (supportedSourceContractSemantics spec selectors hSupported tx + initialWorld) + (nativeGeneratedCallDispatcherResultOf irContract tx + (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots nativeContract) := by + rcases + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_sload0_return32 + spec selectors hSupported irContract tx + (FunctionBody.initialIRStateForTx spec tx initialWorld) + observableSlots hcompile hSelectorRange hSelectorsRange hNoWrap + (fun fn hFind => + generatedFunctionCalldataThreshold_of_compile_ok_supported + spec selectors hSupported irContract tx hcompile fn hFind) + hSourceParams hSourceBody with + ⟨nativeContract, hLower, hMatch⟩ + exact + ⟨nativeContract, hLower, + compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match + spec selectors hSupported irContract tx initialWorld observableSlots + nativeContract htxNormalized hcalldataSizeFits hcompile hMatch⟩ + +/-- Closed generated `callDispatcher` theorem for a selected single-argument +return body `mstore(0, calldataload(4)); return(0, 32)`. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload4_return32 + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (hArgsCons : ∃ arg rest, tx.args = arg :: rest) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit 4]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload4_return32 + irContract tx state observableSlots hArgsCons hReturnBody) + hThreshold + +/-- Closed generated `callDispatcher` theorem for a selected aligned-argument +return body `mstore(0, calldataload(4 + 32*idx)); return(0, 32)`. -/ +private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload_aligned_return32 + (spec : CompilationModel.CompilationModel) (selectors : List Nat) + (hSupported : SupportedSpec spec selectors) + (irContract : IRContract) + (tx : IRTransaction) + (state : IRState) + (observableSlots : List Nat) + (hcompile : CompilationModel.compile spec selectors = Except.ok irContract) + (hSelectorRange : tx.functionSelector < Compiler.Constants.selectorModulus) + (hSelectorsRange : + ∀ selector, selector ∈ selectors → + selector < Compiler.Constants.selectorModulus) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hThreshold : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + 4 + fn.params.length * 32 < EvmYul.UInt256.size) + (idx arg : Nat) + (rest : List Nat) + (hArgDrop : tx.args.drop idx = arg :: rest) + (hOffset64 : 4 + 32 * idx < 2 ^ 64) + (hReturnBody : + ∀ fn, + irContract.functions.find? (fun fn => fn.selector == tx.functionSelector) = + some fn → + fn.body = [ + Yul.YulStmt.expr (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit 0, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit (4 + 32 * idx)]]), + Yul.YulStmt.expr (Yul.YulExpr.call "return" + [Yul.YulExpr.lit 0, Yul.YulExpr.lit 32])]) : + ∃ nativeContract : EvmYul.Yul.Ast.YulContract, + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative + (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧ + nativeResultsMatchOn observableSlots + (interpretIR irContract tx state) + (nativeGeneratedCallDispatcherResultOf irContract tx state + observableSlots nativeContract) := by + exact + nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold + spec selectors hSupported irContract tx state observableSlots hcompile + hSelectorRange hSelectorsRange hNoWrap + (NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload_aligned_return32 + irContract tx state observableSlots idx arg rest hArgDrop hOffset64 + hReturnBody) + hThreshold + +/-- Named SimpleStorage native dispatcher direct-match obligation. -/-- Named SimpleStorage native dispatcher bridge obligation. - -This keeps the remaining native proof seam explicit and sorry-free. The missing -work is to prove that the lowered native dispatcher block selects and executes -the three generated bodies (`store(uint256)`, `retrieve()`, and selector-miss -`revert`) and that the projected native result agrees with the -EVMYulLean-backed interpreter oracle on the caller's observable storage -projection. The generic `callDispatcher` wrapper has already been discharged by -`nativeCallDispatcherAgreesWithInterpreter_of_dispatcherBlock_agree`, and the -dispatcher-block result wrapper has already been discharged by -`nativeDispatcherBlockAgreesWithInterpreter_of_exec_agree`. -/ -def simpleStorageNativeCallDispatcherBridge +The lowered native dispatcher result is compared with `interpretIR` directly +instead of with the EVMYulLean fuel wrapper. -/ +private def simpleStorageNativeCallDispatcherMatchBridge (tx : IRTransaction) (initialState : IRState) (observableSlots : List Nat) : Prop := - nativeDispatcherExecAgreesWithInterpreterPositive + nativeDispatcherExecMatchesIRPositive simpleStorageNativeDispatcherFuel simpleStorageIRContract tx initialState observableSlots Compiler.SimpleStorageNativeWitness.nativeContract -/-! ### Per-case sub-bridges for the SimpleStorage native dispatcher. - -The monolithic `simpleStorageNativeCallDispatcherBridge` bundles three -selector-class obligations: the `retrieve()` hit case, the `store(uint256)` -hit case, and the selector-miss revert case. Splitting it into three -per-case sub-bridges, each gated on the relevant selector hypothesis, -exposes the case structure at the public-theorem boundary so each case -can be discharged independently as the harness lemmas mature. - -Each per-case sub-bridge is *strictly weaker* than the monolithic bridge -because it adds a precondition fixing the selector class, so a proof of -the sub-bridge does not need to do the case analysis on the selector that -a proof of the monolithic bridge would need to do. The combined bridge -is recovered from the three sub-bridges by the -`simpleStorageNativeCallDispatcherBridge_of_per_case` discharger below. -/ - -/-- Per-case sub-bridge: the dispatcher-exec agreement obligation when the -caller-supplied transaction selector matches `retrieve()` (selector -`0x2e64cec1`). -/ -def simpleStorageNativeRetrieveHitBridge +/-! ### Per-case sub-bridges for the SimpleStorage native dispatcher. -/ + +/-- Direct-match per-case sub-bridge for the `retrieve()` selector hit. -/ +private def simpleStorageNativeRetrieveHitMatchBridge (tx : IRTransaction) (initialState : IRState) (observableSlots : List Nat) : Prop := tx.functionSelector % Compiler.Constants.selectorModulus = 0x2e64cec1 → - nativeDispatcherExecAgreesWithInterpreterPositive + nativeDispatcherExecMatchesIRPositive simpleStorageNativeDispatcherFuel simpleStorageIRContract tx initialState observableSlots Compiler.SimpleStorageNativeWitness.nativeContract -/-- Per-case sub-bridge: the dispatcher-exec agreement obligation when the -caller-supplied transaction selector matches `store(uint256)` (selector -`0x6057361d`). -/ -def simpleStorageNativeStoreHitBridge +/-- Direct-match per-case sub-bridge for the `store(uint256)` selector hit. -/ +private def simpleStorageNativeStoreHitMatchBridge (tx : IRTransaction) (initialState : IRState) (observableSlots : List Nat) : Prop := tx.functionSelector % Compiler.Constants.selectorModulus = 0x6057361d → - nativeDispatcherExecAgreesWithInterpreterPositive + nativeDispatcherExecMatchesIRPositive simpleStorageNativeDispatcherFuel simpleStorageIRContract tx initialState observableSlots Compiler.SimpleStorageNativeWitness.nativeContract -/-- Per-case sub-bridge: the dispatcher-exec agreement obligation when the -caller-supplied transaction selector matches neither `store(uint256)` nor -`retrieve()` and the lowered switch falls through to the default -`revert(0, 0)` arm. -/ -def simpleStorageNativeSelectorMissBridge +/-- Direct-match per-case sub-bridge for the selector-miss revert arm. -/ +private def simpleStorageNativeSelectorMissMatchBridge (tx : IRTransaction) (initialState : IRState) (observableSlots : List Nat) : Prop := tx.functionSelector % Compiler.Constants.selectorModulus ≠ 0x2e64cec1 → tx.functionSelector % Compiler.Constants.selectorModulus ≠ 0x6057361d → - nativeDispatcherExecAgreesWithInterpreterPositive + nativeDispatcherExecMatchesIRPositive simpleStorageNativeDispatcherFuel simpleStorageIRContract tx initialState observableSlots Compiler.SimpleStorageNativeWitness.nativeContract -/-- Retrieve-hit native dispatcher bridge discharged against the existing -public entry preconditions. The native initial state materializes literal -storage reads from the emitted runtime, so slot zero is present independently of -the caller's observable slot list. -/ -theorem simpleStorageNativeRetrieveHitBridge_proved +/-- Retrieve-hit direct-match native dispatcher bridge. -/ +private theorem simpleStorageNativeRetrieveHitMatchBridge_proved (tx : IRTransaction) (initialState : IRState) (observableSlots : List Nat) (hselector : tx.functionSelector < selectorModulus) (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) (hdispatchGuardSafe : ∀ fn, fn ∈ simpleStorageIRContract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ simpleStorageIRContract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ simpleStorageIRContract.functions → - HasSelectorDeadBridge fn.body) - (hparamErase : ∀ fn, fn ∈ simpleStorageIRContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) : - simpleStorageNativeRetrieveHitBridge tx initialState observableSlots := by + DispatchGuardsSafe fn tx) : + simpleStorageNativeRetrieveHitMatchBridge tx initialState observableSlots := by intro hRetrieve have hSelectorEq : tx.functionSelector = 0x2e64cec1 := by have hmod := Nat.mod_eq_of_lt hselector @@ -5004,33 +34939,8 @@ theorem simpleStorageNativeRetrieveHitBridge_proved · simp [retrieveFn] at hPayable · exact hZero simpa [evmModulus, EvmYul.UInt256.size] using hzero - have hLayer : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR simpleStorageIRContract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend - .evmYulLean (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := - layer3_contract_preserves_semantics_evmYulLean simpleStorageIRContract tx initialState - hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead - (by intro fn hmem; simp [simpleStorageIRContract] at hmem ⊢; rcases hmem with rfl | rfl <;> rfl) - (by intro s hs; simp [simpleStorageIRContract] at hs) rfl rfl - simpleStorage_functions_bridged have hIR := interpretIR_simpleStorage_retrieveHit tx initialState hSelectorEq - have hLayerFuel : - Compiler.Proofs.YulGeneration.resultsMatch - { success := true - returnValue := some ((initialState.storage (IRStorageSlot.ofNat 0)).toNat) - finalStorage := initialState.storage - finalMappings := Compiler.Proofs.storageAsMappings initialState.storage - events := initialState.events } - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ simpleStorageNativeDispatcherFuel) - (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := by - simpa [hIR, Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend, - simpleStorageNativeDispatcherFuel, simpleStorage_runtimeCode_eq_single_dispatcher] - using hLayer + (by simpa [evmModulus, EvmYul.UInt256.size] using hMsgValue) let yulTx := YulTransaction.ofIR tx let slots := Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots @@ -5103,29 +35013,14 @@ theorem simpleStorageNativeRetrieveHitBridge_proved YulState.initial, EvmYul.State.sload, EvmYul.State.addAccessedStorageKey, EvmYul.Substate.addAccessedStorageKey, EvmYul.Yul.State.sharedState] rfl - have hAgree : - yulResultsAgreeOn observableSlots - { success := true, - returnValue := some p.2.toNat, - finalStorage := - Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState - (YulTransaction.ofIR tx) (EvmYul.Yul.State.Ok shared3 store), - finalMappings := - Compiler.Proofs.storageAsMappings - (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState - (YulTransaction.ofIR tx) (EvmYul.Yul.State.Ok shared3 store)), - events := - initialState.events ++ - Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState - (EvmYul.Yul.State.Ok shared3 store) } - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ simpleStorageNativeDispatcherFuel) - (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := by - rcases hLayerFuel with ⟨hsuccess, hreturnValue, hstorage, _hmappings, hevents⟩ - refine ⟨?_, ?_, ?_, ?_⟩ - · exact hsuccess - · simpa [hp] using hreturnValue + apply nativeDispatcherExecMatchesIRPositive_of_exec_yulHalt_project_eq_match + (haltState := EvmYul.Yul.State.Ok shared3 store) (haltValue := ⟨1⟩) + · simpa [simpleStorage_runtimeCode_eq_single_dispatcher, yulTx, slots, + shared, p, shared1, shared2, shared3] using hExec + · exact hProject + · rw [hIR] + refine ⟨rfl, ?_, ?_, ?_⟩ + · simp [hp, Compiler.Proofs.IRGeneration.IRStorageWord.toNat] · intro slot hslot have hslot' : slot ∈ slots := by simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots, @@ -5134,38 +35029,22 @@ theorem simpleStorageNativeRetrieveHitBridge_proved Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState_retrieveHit_initialState_materialized Compiler.SimpleStorageNativeWitness.nativeContract yulTx initialState.storage slots store slot hslot' - exact (hNative.trans (hstorage (IRStorageSlot.ofNat slot))) + exact hNative.symm · rw [hLogs, List.append_nil] - exact hevents - apply nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_yulHalt_project_eq_agree - (haltState := EvmYul.Yul.State.Ok shared3 store) (haltValue := ⟨1⟩) - · simpa [simpleStorage_runtimeCode_eq_single_dispatcher, yulTx, slots, - shared, p, shared1, shared2, shared3] using hExec - · exact hProject - · exact hAgree - -/-- Store-hit native dispatcher bridge discharged against the existing public -entry preconditions. The proof splits on whether the setter calldata argument -is present: short calldata follows the native `revert(0,0)` argument guard, -while present calldata executes the generated `sstore(0, calldataload(4)); -stop` body and compares projected storage on materialized observable slots. -/ -theorem simpleStorageNativeStoreHitBridge_proved + +/-- Store-hit direct-match native dispatcher bridge. + +The proof splits on the setter calldata argument. Short calldata projects the +native argument-guard revert directly to the IR arity failure; present calldata +uses the closed-form native store halt and compares projected storage on the +materialized observable slots. -/ +private theorem simpleStorageNativeStoreHitMatchBridge_proved (tx : IRTransaction) (initialState : IRState) (observableSlots : List Nat) (hselector : tx.functionSelector < selectorModulus) (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) (hdispatchGuardSafe : ∀ fn, fn ∈ simpleStorageIRContract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ simpleStorageIRContract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ simpleStorageIRContract.functions → - HasSelectorDeadBridge fn.body) - (hparamErase : ∀ fn, fn ∈ simpleStorageIRContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) : - simpleStorageNativeStoreHitBridge tx initialState observableSlots := by + DispatchGuardsSafe fn tx) : + simpleStorageNativeStoreHitMatchBridge tx initialState observableSlots := by intro hStore have hSelectorEq : tx.functionSelector = 0x6057361d := by have hmod := Nat.mod_eq_of_lt hselector @@ -5191,18 +35070,6 @@ theorem simpleStorageNativeStoreHitBridge_proved · simp [storeFn] at hPayable · exact hZero simpa [evmModulus, EvmYul.UInt256.size] using hzero - have hLayer : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR simpleStorageIRContract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend - .evmYulLean (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := - layer3_contract_preserves_semantics_evmYulLean simpleStorageIRContract tx initialState - hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead - (by intro fn hmem; simp [simpleStorageIRContract] at hmem ⊢; rcases hmem with rfl | rfl <;> rfl) - (by intro s hs; simp [simpleStorageIRContract] at hs) rfl rfl - simpleStorage_functions_bridged let yulTx := YulTransaction.ofIR tx let slots := Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots @@ -5211,22 +35078,7 @@ theorem simpleStorageNativeStoreHitBridge_proved | nil => have hIR := interpretIR_simpleStorage_storeHit_short tx initialState hSelectorEq hArgs - have hLayerFuel : - Compiler.Proofs.YulGeneration.resultsMatch - { success := false - returnValue := none - finalStorage := initialState.storage - finalMappings := Compiler.Proofs.storageAsMappings initialState.storage - events := initialState.events } - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ simpleStorageNativeDispatcherFuel) - (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := by - simpa [hIR, Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend, - simpleStorageNativeDispatcherFuel, simpleStorage_runtimeCode_eq_single_dispatcher] - using hLayer - rcases hLayerFuel with ⟨hsuccess, hreturnValue, hstorage, _hmappings, hevents⟩ - refine nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_error_project_eq_agree + refine nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match (err := EvmYul.Yul.Exception.Revert) (nativeYul := { success := false @@ -5245,34 +35097,12 @@ theorem simpleStorageNativeStoreHitBridge_proved (by simpa [yulTx, YulTransaction.ofIR, evmModulus] using hNoWrap) (by simpa [yulTx, YulTransaction.ofIR] using hMsgValue)) · rfl - · refine ⟨?_, ?_, ?_, ?_⟩ - · exact hsuccess - · exact hreturnValue - · intro slot _ - exact hstorage (IRStorageSlot.ofNat slot) - · exact hevents + · rw [hIR] + exact ⟨rfl, rfl, (by intro slot _; rfl), rfl⟩ | cons arg rest => have hIR := interpretIR_simpleStorage_storeHit_arg tx initialState arg rest hSelectorEq hArgs - have hLayerFuel : - Compiler.Proofs.YulGeneration.resultsMatch - { success := true - returnValue := none - finalStorage := - Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 - (arg % evmModulus) - finalMappings := - Compiler.Proofs.storageAsMappings - (Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 - (arg % evmModulus)) - events := initialState.events } - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ simpleStorageNativeDispatcherFuel) - (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := by - simpa [hIR, Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend, - simpleStorageNativeDispatcherFuel, simpleStorage_runtimeCode_eq_single_dispatcher] - using hLayer + (by simpa [evmModulus, EvmYul.UInt256.size] using hMsgValue) obtain ⟨store, haltState, hExec, hHaltState⟩ := simpleStorageNativeContract_dispatcherExec_storeHit_halt_atFuel yulTx initialState.storage slots arg rest @@ -5315,79 +35145,39 @@ theorem simpleStorageNativeStoreHitBridge_proved EvmYul.Account.updateStorage, EvmYul.Substate.addAccessedStorageKey, Option.option] split <;> rfl - have hAgree : - yulResultsAgreeOn observableSlots - { success := true, - returnValue := none, - finalStorage := - Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState - (YulTransaction.ofIR tx) haltState, - finalMappings := - Compiler.Proofs.storageAsMappings - (Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState - (YulTransaction.ofIR tx) haltState), - events := - initialState.events ++ - Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState - haltState } - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean (Nat.succ simpleStorageNativeDispatcherFuel) - (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := by - rcases hLayerFuel with ⟨hsuccess, hreturnValue, hstorage, _hmappings, hevents⟩ - refine ⟨?_, ?_, ?_, ?_⟩ - · exact hsuccess - · exact hreturnValue + apply nativeDispatcherExecMatchesIRPositive_of_exec_yulHalt_project_eq_match + (haltState := haltState) (haltValue := ⟨0⟩) + · simpa [simpleStorage_runtimeCode_eq_single_dispatcher, yulTx, slots] using hExec + · exact hProject + · rw [hIR] + refine ⟨rfl, rfl, ?_, ?_⟩ · intro slot hslot have hslot' : slot ∈ slots := by simp [slots, Compiler.Proofs.YulGeneration.Backends.Native.materializedStorageSlots, hslot] have hNative := projectStorageFromState_storeHit_initialState_materialized - yulTx initialState.storage slots store arg slot hslot' - have hNative' : - Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState - (YulTransaction.ofIR tx) haltState (IRStorageSlot.ofNat slot) = - (Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 - (arg % evmModulus)) (IRStorageSlot.ofNat slot) := by - subst hHaltState - rw [hNative] - have hArgMod : - EvmYul.UInt256.ofNat arg = - EvmYul.UInt256.ofNat (arg % evmModulus) := by - unfold EvmYul.UInt256.ofNat - simp [Id.run, Fin.ofNat, evmModulus, EvmYul.UInt256.size] - simp [Compiler.Proofs.abstractStoreStorageOrMapping, - Compiler.Proofs.IRGeneration.IRStorageWord.ofNat, hArgMod] - exact hNative'.trans (hstorage (IRStorageSlot.ofNat slot)) + Compiler.SimpleStorageNativeWitness.nativeContract yulTx + initialState.storage slots store arg slot hslot' + have hArgMod : + EvmYul.UInt256.ofNat arg = + EvmYul.UInt256.ofNat (arg % evmModulus) := by + unfold EvmYul.UInt256.ofNat + simp [Id.run, Fin.ofNat, evmModulus, EvmYul.UInt256.size] + simpa [hHaltState, Compiler.Proofs.abstractStoreStorageOrMapping, + Compiler.Proofs.IRGeneration.IRStorageWord.ofNat, hArgMod] using hNative.symm · rw [hLogs, List.append_nil] - exact hevents - apply nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_yulHalt_project_eq_agree - (haltState := haltState) (haltValue := ⟨0⟩) - · simpa [simpleStorage_runtimeCode_eq_single_dispatcher, yulTx, slots] using hExec - · exact hProject - · exact hAgree -/-- Selector-miss native dispatcher bridge discharged against the existing -public entry preconditions. The native selector-miss path reverts, so -`projectResult` preserves the parameter-passed initial storage directly. -/ -theorem simpleStorageNativeSelectorMissBridge_proved +/-- Selector-miss direct-match native dispatcher bridge. + +The native selector-miss path projects to the same revert result as the IR +selector-miss interpreter case, so this proof avoids the compatibility +fuel-wrapper bridge entirely. -/ +private theorem simpleStorageNativeSelectorMissMatchBridge_proved (tx : IRTransaction) (initialState : IRState) (observableSlots : List Nat) (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hdispatchGuardSafe : ∀ fn, fn ∈ simpleStorageIRContract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ simpleStorageIRContract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ simpleStorageIRContract.functions → - HasSelectorDeadBridge fn.body) - (hparamErase : ∀ fn, fn ∈ simpleStorageIRContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) : - simpleStorageNativeSelectorMissBridge tx initialState observableSlots := by + (hNoWrap : 4 + tx.args.length * 32 < evmModulus) : + simpleStorageNativeSelectorMissMatchBridge tx initialState observableSlots := by intro hSelMissRetrieve hSelMissStore have hSelEq : tx.functionSelector % selectorModulus = tx.functionSelector := Nat.mod_eq_of_lt hselector @@ -5397,28 +35187,9 @@ theorem simpleStorageNativeSelectorMissBridge_proved have hSelMissTxRetrieve : tx.functionSelector ≠ 0x2e64cec1 := by rw [← hSelEq] exact hSelMissRetrieve - have hLayer3 : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR simpleStorageIRContract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend - .evmYulLean (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := - layer3_contract_preserves_semantics_evmYulLean simpleStorageIRContract tx initialState - hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead - (by intro fn hmem; simp [simpleStorageIRContract] at hmem ⊢; rcases hmem with rfl | rfl <;> rfl) - (by intro s hs; simp [simpleStorageIRContract] at hs) rfl rfl - simpleStorage_functions_bridged have hIR := interpretIR_simpleStorage_selectorMiss tx initialState hSelMissTxStore hSelMissTxRetrieve - rw [hIR] at hLayer3 - have hSizeEq : - sizeOf (Compiler.emitYul simpleStorageIRContract).runtimeCode = - simpleStorageNativeDispatcherFuel := by - rw [simpleStorage_runtimeCode_eq_single_dispatcher] - rfl - rcases hLayer3 with ⟨hsuccess, hreturnValue, hstorage, _hmappings, hevents⟩ - refine nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_error_project_eq_agree + refine nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match (err := EvmYul.Yul.Exception.Revert) (nativeYul := { success := false @@ -5444,40 +35215,21 @@ theorem simpleStorageNativeSelectorMissBridge_proved change 4 + tx.args.length * 32 < EvmYul.UInt256.size simpa [evmModulus, EvmYul.UInt256.size] using hNoWrap · rfl - · show yulResultsAgreeOn observableSlots _ - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackendFuel - .evmYulLean simpleStorageNativeDispatcherFuel.succ - (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) - have hFuelGoal : - (simpleStorageNativeDispatcherFuel.succ : Nat) = - sizeOf (Compiler.emitYul simpleStorageIRContract).runtimeCode + 1 := by - rw [hSizeEq] - rw [hFuelGoal] - show yulResultsAgreeOn observableSlots _ - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend - .evmYulLean (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) - refine ⟨?_, ?_, ?_, ?_⟩ - · exact hsuccess - · exact hreturnValue - · intro slot _ - exact hstorage (IRStorageSlot.ofNat slot) - · exact hevents - -/-- Recover the monolithic `simpleStorageNativeCallDispatcherBridge` from the -three per-case sub-bridges by case analysis on -`tx.functionSelector % selectorModulus`. -/ -theorem simpleStorageNativeCallDispatcherBridge_of_per_case + · rw [hIR] + exact ⟨rfl, rfl, (by intro slot _; rfl), rfl⟩ + +/-- Recover the direct-match monolithic SimpleStorage dispatcher obligation +from the three direct per-case sub-bridges. -/ +private theorem simpleStorageNativeCallDispatcherMatchBridge_of_per_case (tx : IRTransaction) (initialState : IRState) (observableSlots : List Nat) (hRetrieveHit : - simpleStorageNativeRetrieveHitBridge tx initialState observableSlots) + simpleStorageNativeRetrieveHitMatchBridge tx initialState observableSlots) (hStoreHit : - simpleStorageNativeStoreHitBridge tx initialState observableSlots) + simpleStorageNativeStoreHitMatchBridge tx initialState observableSlots) (hSelectorMiss : - simpleStorageNativeSelectorMissBridge tx initialState observableSlots) : - simpleStorageNativeCallDispatcherBridge tx initialState observableSlots := by - unfold simpleStorageNativeCallDispatcherBridge + simpleStorageNativeSelectorMissMatchBridge tx initialState observableSlots) : + simpleStorageNativeCallDispatcherMatchBridge tx initialState observableSlots := by + unfold simpleStorageNativeCallDispatcherMatchBridge by_cases hR : tx.functionSelector % Compiler.Constants.selectorModulus = 0x2e64cec1 · exact hRetrieveHit hR @@ -5486,189 +35238,109 @@ theorem simpleStorageNativeCallDispatcherBridge_of_per_case · exact hStoreHit hS · exact hSelectorMiss hR hS -/-- SimpleStorage end-to-end: compile → IR → EVMYulLean-backed Yul preserves -semantics. The concrete function-body bridge witnesses are discharged above. -/ -theorem simpleStorage_endToEnd_evmYulLean - (tx : IRTransaction) (initialState : IRState) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) - (hdispatchGuardSafe : ∀ fn, fn ∈ simpleStorageIRContract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ simpleStorageIRContract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ simpleStorageIRContract.functions → - HasSelectorDeadBridge fn.body) - (hparamErase : ∀ fn, fn ∈ simpleStorageIRContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) : - Compiler.Proofs.YulGeneration.resultsMatch - (interpretIR simpleStorageIRContract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend - .evmYulLean (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) initialState.storage initialState.events) := - layer3_contract_preserves_semantics_evmYulLean simpleStorageIRContract tx initialState - hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead - (by intro fn hmem; simp [simpleStorageIRContract] at hmem ⊢; rcases hmem with rfl | rfl <;> rfl) - (by intro s hs; simp [simpleStorageIRContract] at hs) rfl rfl - simpleStorage_functions_bridged - -/-- Native SimpleStorage wrapper with the lowering seam discharged. - -This reduces the remaining concrete native proof work for `simpleStorage` to -two facts: -- the emitted runtime passes native environment validation for the current tx; -- the lowered native `callDispatcher` agrees with the interpreter oracle. -The concrete lowering witness is computed outside `Compiler/Proofs` and consumed -here only through its exported equality. -/ -theorem simpleStorage_endToEnd_native_evmYulLean_of_callDispatcher_bridge +/-- Native SimpleStorage end-to-end theorem over the direct projected +`EvmYul.Yul.callDispatcher` result. -/ +theorem simpleStorage_endToEnd_native_evmYulLean (tx : IRTransaction) (initialState : IRState) (observableSlots : List Nat) (hselector : tx.functionSelector < selectorModulus) (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) (hdispatchGuardSafe : ∀ fn, fn ∈ simpleStorageIRContract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ simpleStorageIRContract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ simpleStorageIRContract.functions → - HasSelectorDeadBridge fn.body) - (hparamErase : ∀ fn, fn ∈ simpleStorageIRContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) - (hEnv : - Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment - (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) = .ok ()) - (hNativeCallDispatcher : - nativeCallDispatcherAgreesWithInterpreter - (sizeOf (Compiler.emitYul simpleStorageIRContract).runtimeCode + 1) - simpleStorageIRContract tx initialState observableSlots - Compiler.SimpleStorageNativeWitness.nativeContract) : + DispatchGuardsSafe fn tx) : nativeResultsMatchOn observableSlots (interpretIR simpleStorageIRContract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative - (sizeOf (Compiler.emitYul simpleStorageIRContract).runtimeCode + 1) - simpleStorageIRContract tx initialState observableSlots) := - layer3_contract_preserves_semantics_native_of_lowered_callDispatcher_bridge - (sizeOf (Compiler.emitYul simpleStorageIRContract).runtimeCode + 1) - simpleStorageIRContract tx initialState observableSlots - Compiler.SimpleStorageNativeWitness.nativeContract - hselector hNoWrap hvars hmemory htransient hreturn hparamErase - hdispatchGuardSafe hNoHasSelector hHasSelectorDead - (by - intro fn hmem - simp [simpleStorageIRContract] at hmem ⊢ - rcases hmem with rfl | rfl <;> rfl) - (by intro s hs; simp [simpleStorageIRContract] at hs) - rfl - rfl - simpleStorage_functions_bridged - rfl - Compiler.SimpleStorageNativeWitness.generatedRuntimeNativeFragment_eq - Compiler.SimpleStorageNativeWitness.lowerRuntimeContractNative_eq - hEnv - hNativeCallDispatcher + (nativeGeneratedCallDispatcherResultOf simpleStorageIRContract tx + initialState observableSlots + Compiler.SimpleStorageNativeWitness.nativeContract) := by + have hConcrete : + simpleStorageNativeCallDispatcherMatchBridge tx initialState + observableSlots := + simpleStorageNativeCallDispatcherMatchBridge_of_per_case + tx initialState observableSlots + (simpleStorageNativeRetrieveHitMatchBridge_proved tx initialState + observableSlots hselector hNoWrap hdispatchGuardSafe) + (simpleStorageNativeStoreHitMatchBridge_proved tx initialState + observableSlots hselector hNoWrap hdispatchGuardSafe) + (simpleStorageNativeSelectorMissMatchBridge_proved tx initialState + observableSlots hselector hNoWrap) + unfold simpleStorageNativeCallDispatcherMatchBridge at hConcrete + unfold nativeDispatcherExecMatchesIRPositive at hConcrete + unfold nativeGeneratedCallDispatcherResultOf + dsimp at hConcrete ⊢ + rw [ + Compiler.Proofs.YulGeneration.Backends.Native.callDispatcher_succ_eq_callDispatcherBlockResult, + Compiler.Proofs.YulGeneration.Backends.Native.callDispatcherBlockResult_initialState_eq_contractDispatcherBlockResult, + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherBlockResult_eq_execResult + ] + simpa [simpleStorageNativeDispatcherFuel, simpleStorage_runtimeCode_eq_single_dispatcher] + using hConcrete -/-- Native SimpleStorage end-to-end theorem with the concrete native dispatcher -bridge fully discharged for retrieve hit, store hit, and selector miss. -/ -theorem simpleStorage_endToEnd_native_evmYulLean +/-- Source-level SimpleStorage native theorem from any already established +source-to-IR result match. + +The concrete native dispatcher bridge proves `interpretIR` agrees with the +projected `EvmYul.Yul.callDispatcher` result; this wrapper composes that fact +with the standard source-to-IR result surface. -/ +theorem simpleStorage_source_endToEnd_native_evmYulLean_of_sourceIR (tx : IRTransaction) (initialState : IRState) (observableSlots : List Nat) + (source : SourceSemantics.SourceContractResult) (hselector : tx.functionSelector < selectorModulus) (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hvars : initialState.vars = []) - (hmemory : initialState.memory = fun _ => 0) - (htransient : initialState.transientStorage = fun _ => 0) - (hreturn : initialState.returnValue = none) (hdispatchGuardSafe : ∀ fn, fn ∈ simpleStorageIRContract.functions → DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ simpleStorageIRContract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ simpleStorageIRContract.functions → - HasSelectorDeadBridge fn.body) - (hparamErase : ∀ fn, fn ∈ simpleStorageIRContract.functions → - paramLoadErasure fn tx (initialState.withTx tx)) - (hEnv : - Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment - (Compiler.emitYul simpleStorageIRContract).runtimeCode - (YulTransaction.ofIR tx) = .ok ()) : - nativeResultsMatchOn observableSlots - (interpretIR simpleStorageIRContract tx initialState) - (Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative - (sizeOf (Compiler.emitYul simpleStorageIRContract).runtimeCode + 1) - simpleStorageIRContract tx initialState observableSlots) := - simpleStorage_endToEnd_native_evmYulLean_of_callDispatcher_bridge - tx initialState observableSlots hselector hNoWrap hvars hmemory htransient - hreturn hdispatchGuardSafe hNoHasSelector hHasSelectorDead hparamErase hEnv - (nativeCallDispatcherAgreesWithInterpreter_of_dispatcherBlock_agree - (nativeDispatcherBlockAgreesWithInterpreter_of_exec_agree - (nativeDispatcherExecAgreesWithInterpreter_of_positive - (by - rw [simpleStorage_runtimeCode_eq_single_dispatcher] - exact simpleStorageNativeCallDispatcherBridge_of_per_case - tx initialState observableSlots - (simpleStorageNativeRetrieveHitBridge_proved tx initialState - observableSlots hselector hNoWrap hvars hmemory htransient - hreturn hdispatchGuardSafe hNoHasSelector hHasSelectorDead - hparamErase) - (simpleStorageNativeStoreHitBridge_proved tx initialState - observableSlots hselector hNoWrap hvars hmemory htransient - hreturn hdispatchGuardSafe hNoHasSelector hHasSelectorDead - hparamErase) - (simpleStorageNativeSelectorMissBridge_proved tx initialState - observableSlots hselector hNoWrap hvars hmemory htransient - hreturn hdispatchGuardSafe hNoHasSelector hHasSelectorDead - hparamErase))))) + (hSourceIR : + Compiler.Proofs.IRGeneration.FunctionBody.sourceResultMatchesIRResult + source (interpretIR simpleStorageIRContract tx initialState)) : + sourceResultMatchesNativeOn observableSlots source + (nativeGeneratedCallDispatcherResultOf simpleStorageIRContract tx + initialState observableSlots + Compiler.SimpleStorageNativeWitness.nativeContract) := by + exact + sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn + hSourceIR + (simpleStorage_endToEnd_native_evmYulLean tx initialState observableSlots + hselector hNoWrap hdispatchGuardSafe) /-! ## Universal Pure Arithmetic Bridge The pure arithmetic bridge proofs (`pure_add_bridge`, etc.) were removed -after the `evalBuiltinCall` refactor (commit e5da6c7f) which added -`callvalue`/`calldatasize` support, making `evalBuiltinCall` too large -for the default heartbeat limit during type-checking. The proofs were -mathematically correct but need `evalBuiltinCall` to be factored into -smaller pieces before they can be re-stated without timeout. +after the legacy builtin dispatch grew `callvalue`/`calldatasize` +support, making the old monolithic wrapper too large for the default +heartbeat limit during type-checking. The proofs were mathematically +correct but need the legacy builtin dispatch to be factored into smaller +pieces before they can be re-stated without timeout. See: `ArithmeticProfile.lean` and `YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean` for the current replacement coverage: universal bridge lemmas for all pure bridged builtins. -/ -/-! ## Phase 4: EVMYulLean as Semantic Target - -The historical Yul execution semantics used throughout this file dispatch builtins via -`evalBuiltinCallWithBackendContext defaultBuiltinBackend`, where -`defaultBuiltinBackend = .verity`. The EVMYulLean bridge -(`EvmYulLeanBridgeLemmas.lean`) proves that for all 36 bridged builtins, -the `.verity` and `.evmYulLean` backends produce identical results. - -This means the existing preservation theorems above are pointwise valid under -EVMYulLean semantics for any single bridged-builtin call site whose bridge -dependencies are fully proven. The retargeting module -(`EvmYulLeanRetarget.lean`) makes this explicit with -`backends_agree_on_bridged_builtins`, lifts it through `BridgedExpr` -expression evaluation, proves statement-fragment helpers for straight-line, -block, if, switch, and for cases, and now proves recursive -`BridgedTarget` execution equivalence. It also proves +/-! ## EVMYulLean Semantic Targets + +The public native theorem surface in this file targets the direct projected +`EvmYul.Yul.callDispatcher` result through `nativeGeneratedCallDispatcherResultOf`. +The older `nativeIRRuntimeMatchesIR` and generated dispatcher-exec theorem +families remain file-local transition evidence. EndToEnd no longer defines +compatibility wrappers over the older backend-parameterized proof-interpreter +surface. + +The retargeting module (`EvmYulLeanRetarget.lean`) still internally records the +bridge-history facts: `backends_agree_on_bridged_builtins`, `BridgedExpr` +expression lifting, statement-fragment helpers for straight-line, block, if, +switch, and for cases, and recursive `BridgedTarget` execution equivalence. +Those file-local facts remain useful as transition evidence for the bridged +fragment, but they are no longer composed into this file's compiler-correctness theorems. The +retargeting module also proves `emitYul_runtimeCode_bridged`, the emitted-runtime closure witness conditional on bridged IR function, entrypoint, and internal helper bodies, and `emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies`, the corresponding - emitted-runtime equality between Verity `execYulFuel` and the EVMYulLean - backend executor under those body witnesses. These theorems compose the - fully proven builtin bridge equivalences. It also proves - `yulCodegen_preserves_semantics_evmYulLean`, the lower-level Layer-3 theorem - whose Yul side is the EVMYulLean backend runtime. This file now exposes - EndToEnd wrappers - `layer3_contract_preserves_semantics_evmYulLean_with_function_bridge`, - `layer3_contract_preserves_semantics_evmYulLean`, - `layers2_3_ir_matches_yul_evmYulLean`, and - `simpleStorage_endToEnd_evmYulLean` over that target. The public - `layers2_3_ir_matches_yul_evmYulLean` wrapper discharges raw external - function-body bridge witnesses from `SupportedSpec`, static-parameter + emitted-runtime equality between the transition proof-interpreter backend and + the EVMYulLean backend executor under those body witnesses. These theorems compose the + fully proven builtin bridge equivalences. This file intentionally does not + define EndToEnd wrappers over that proof-interpreter backend target; the + public EndToEnd theorem family targets native dispatcher execution through + the direct projected `nativeGeneratedCallDispatcherResultOf` result. + The body-closure increments prove that generated external function bodies can + discharge raw `BridgedStmts` witnesses from `SupportedSpec`, static-parameter witnesses, and `BridgedSafeStmts` source-body witnesses. Body-closure increments also prove scalar and static-scalar calldata parameter prologues satisfy `BridgedStmts`, pure source-expression fragments @@ -5685,20 +35357,30 @@ on bridged IR function, entrypoint, and internal helper bodies, and - The generated runtime dispatch wrapper is now known to satisfy `BridgedTarget` and execute equivalently under the EVMYulLean backend when the IR bodies it embeds satisfy `BridgedStmt`. -- Layer 3 now has a contract-level theorem targeting - `interpretYulRuntimeWithBackend .evmYulLean`; the public safe-body wrapper - derives its raw body witnesses from supported source bodies. -- This public EndToEnd module now has a safe-body wrapper targeting - `interpretYulRuntimeWithBackend .evmYulLean` without raw `BridgedStmts` - body hypotheses; the historical - `layers2_3_ir_matches_yul_via_reference_oracle` wrapper remains available - for the Verity-backed `interpretYulFromIR` target. +- Layer 3 no longer keeps EndToEnd compatibility lemmas targeting the + proof-interpreter EVMYulLean backend; the public EndToEnd theorem family + targets native dispatcher execution through the direct projected + `nativeGeneratedCallDispatcherResultOf` result. +- The historical Verity-backed public oracle-routed EndToEnd wrappers + have been removed. - Scalar and static-scalar calldata parameter-loading prologues are now known to satisfy `BridgedStmts`. -- Scalar source expression leaves and the pure arithmetic/comparison/bit-operation - `BridgedSourceExpr` fragment are now known to compile to `BridgedExpr`. +- The `ExprCompileCore` expression grammar is now known to lift into + `BridgedSourceExpr`, including environment reads, `calldatasize`, + branchless helpers, and calldata/memory/transient unary reads. +- Singleton `mstore`/`tstore` bodies whose offset and value are + `ExprCompileCore` are now known to satisfy `BridgedSafeStmts`, matching the + `SupportedFragment.mstoreSingle` and `SupportedFragment.tstoreSingle` + source shapes. +- Simple `setStorage`, `setStorageAddr`, and `require` source-body lists now + have direct `BridgedSafeStmts` constructors. The singleton uint/address + storage and literal guard-family shapes exposed by `SupportedFragment` can be + discharged from their compile-core and field-layout witnesses. - Scalar-leaf and pure-expression `letVar`/`assignVar` statement lists are now known to compile to `BridgedStmts`. +- External `StmtListCompileCore` and `StmtListTerminalCore` bodies now have + direct `BridgedSafeStmts` packagers through the native recursive raw-log + source fragment. - Pure-binding plus unpacked single-slot `setStorage` statement lists and external `stop`/`return` terminators are now known to compile to `BridgedStmts`. diff --git a/Compiler/Proofs/IRGeneration/Contract.lean b/Compiler/Proofs/IRGeneration/Contract.lean index 9697d787b..7dfa72920 100644 --- a/Compiler/Proofs/IRGeneration/Contract.lean +++ b/Compiler/Proofs/IRGeneration/Contract.lean @@ -557,6 +557,80 @@ private theorem compileValidatedCore_ok_yields_internalFunctions_nil cases hcore rfl +private theorem compileValidatedCore_ok_yields_noFallbackEntrypoint + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcore : compileValidatedCore model selectors = Except.ok ir) : + ir.fallbackEntrypoint = none := by + have hfallback : + pickUniqueFunctionByName "fallback" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "fallback" model.functions hSupported.noFallback + have hreceive : + pickUniqueFunctionByName "receive" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "receive" model.functions hSupported.noReceive + unfold compileValidatedCore at hcore + rw [hfallback, hreceive] at hcore + simp only [bind, Except.bind, Option.mapM_none, pure, Except.pure] at hcore + rcases hmap : + ((model.functions.filter + (fun fn => !fn.isInternal && !isInteropEntrypointName fn.name)).zip selectors).mapM + (fun x => compileFunctionSpec (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes x.2 x.1) with _ | irFns + · simp [hmap] at hcore + · rcases hinternal : + (model.functions.filter (·.isInternal)).mapM + (compileInternalFunction (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes) with _ | internalFuncDefs + · simp [hmap, hinternal] at hcore + · rcases hctor : + compileConstructor (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes model.constructor with _ | deployStmts + · simp [hmap, hinternal, hctor] at hcore + · simp [hmap, hinternal, hctor] at hcore + cases hcore + rfl + +private theorem compileValidatedCore_ok_yields_noReceiveEntrypoint + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcore : compileValidatedCore model selectors = Except.ok ir) : + ir.receiveEntrypoint = none := by + have hfallback : + pickUniqueFunctionByName "fallback" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "fallback" model.functions hSupported.noFallback + have hreceive : + pickUniqueFunctionByName "receive" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "receive" model.functions hSupported.noReceive + unfold compileValidatedCore at hcore + rw [hfallback, hreceive] at hcore + simp only [bind, Except.bind, Option.mapM_none, pure, Except.pure] at hcore + rcases hmap : + ((model.functions.filter + (fun fn => !fn.isInternal && !isInteropEntrypointName fn.name)).zip selectors).mapM + (fun x => compileFunctionSpec (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes x.2 x.1) with _ | irFns + · simp [hmap] at hcore + · rcases hinternal : + (model.functions.filter (·.isInternal)).mapM + (compileInternalFunction (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes) with _ | internalFuncDefs + · simp [hmap, hinternal] at hcore + · rcases hctor : + compileConstructor (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes model.constructor with _ | deployStmts + · simp [hmap, hinternal, hctor] at hcore + · simp [hmap, hinternal, hctor] at hcore + cases hcore + rfl + theorem supported_params_of_supportedSpec (model : CompilationModel) (selectors : List Nat) @@ -739,6 +813,44 @@ theorem compile_ok_yields_internalFunctions_nil (ir := ir) (hcore := hcompile) +theorem compile_ok_yields_noFallbackEntrypoint + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcompile : CompilationModel.compile model selectors = Except.ok ir) : + ir.fallbackEntrypoint = none := by + unfold CompilationModel.compile at hcompile + simp only [bind, Except.bind] at hcompile + rcases hvalidate : validateCompileInputs model selectors with _ | validated + · simp [hvalidate] at hcompile + · simp [hvalidate] at hcompile + exact compileValidatedCore_ok_yields_noFallbackEntrypoint + (model := model) + (selectors := selectors) + (hSupported := hSupported) + (ir := ir) + (hcore := hcompile) + +theorem compile_ok_yields_noReceiveEntrypoint + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcompile : CompilationModel.compile model selectors = Except.ok ir) : + ir.receiveEntrypoint = none := by + unfold CompilationModel.compile at hcompile + simp only [bind, Except.bind] at hcompile + rcases hvalidate : validateCompileInputs model selectors with _ | validated + · simp [hvalidate] at hcompile + · simp [hvalidate] at hcompile + exact compileValidatedCore_ok_yields_noReceiveEntrypoint + (model := model) + (selectors := selectors) + (hSupported := hSupported) + (ir := ir) + (hcore := hcompile) + theorem compile_ok_yields_internalFunctions_nil_except_mapping_writes (model : CompilationModel) (selectors : List Nat) @@ -787,6 +899,102 @@ theorem compile_ok_yields_internalFunctions_nil_except_mapping_writes cases hir rfl +theorem compile_ok_yields_noFallbackEntrypoint_except_mapping_writes + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpecExceptMappingWrites model selectors) + (ir : IRContract) + (hcompile : CompilationModel.compile model selectors = Except.ok ir) : + ir.fallbackEntrypoint = none := by + have hfallback : + pickUniqueFunctionByName "fallback" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "fallback" model.functions hSupported.noFallback + have hreceive : + pickUniqueFunctionByName "receive" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "receive" model.functions hSupported.noReceive + have hnoInternalFns : + model.functions.filter (·.isInternal) = [] := + filterInternalFunctions_eq_nil_of_supported_except_mapping_writes model selectors hSupported + have harray : contractUsesArrayElement model = false := + hSupported.contractUsesArrayElement_eq_false + have hstorageArray : contractUsesStorageArrayElement model = false := + hSupported.contractUsesStorageArrayElement_eq_false + have hdynamicBytesEq : contractUsesDynamicBytesEq model = false := + hSupported.contractUsesDynamicBytesEq_eq_false + unfold CompilationModel.compile at hcompile + simp only [bind, Except.bind] at hcompile + rcases hvalidate : validateCompileInputs model selectors with _ | validated + · simp [hvalidate] at hcompile + · simp [hvalidate] at hcompile + unfold compileValidatedCore at hcompile + rw [hSupported.normalizedFields, hfallback, hreceive, + contractUsesPlainArrayElement, contractUsesArrayElementWord, harray, + hstorageArray, hdynamicBytesEq, hnoInternalFns, hSupported.noAdtTypes] at hcompile + simp only [bind, Except.bind, pure, Except.pure, List.mapM_nil] at hcompile + rcases hmap : + ((model.functions.filter + (fun fn => !fn.isInternal && !isInteropEntrypointName fn.name)).zip selectors).mapM + (fun x => compileFunctionSpec model.fields model.events model.errors [] x.2 x.1) with _ | irFns + · simp [hmap] at hcompile + · rcases hctor : + compileConstructor model.fields model.events model.errors [] model.constructor with _ | deployStmts + · simp [hmap, hctor] at hcompile + cases hcompile + · simp [hmap, hctor] at hcompile + injection hcompile with hir + cases hir + rfl + +theorem compile_ok_yields_noReceiveEntrypoint_except_mapping_writes + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpecExceptMappingWrites model selectors) + (ir : IRContract) + (hcompile : CompilationModel.compile model selectors = Except.ok ir) : + ir.receiveEntrypoint = none := by + have hfallback : + pickUniqueFunctionByName "fallback" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "fallback" model.functions hSupported.noFallback + have hreceive : + pickUniqueFunctionByName "receive" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "receive" model.functions hSupported.noReceive + have hnoInternalFns : + model.functions.filter (·.isInternal) = [] := + filterInternalFunctions_eq_nil_of_supported_except_mapping_writes model selectors hSupported + have harray : contractUsesArrayElement model = false := + hSupported.contractUsesArrayElement_eq_false + have hstorageArray : contractUsesStorageArrayElement model = false := + hSupported.contractUsesStorageArrayElement_eq_false + have hdynamicBytesEq : contractUsesDynamicBytesEq model = false := + hSupported.contractUsesDynamicBytesEq_eq_false + unfold CompilationModel.compile at hcompile + simp only [bind, Except.bind] at hcompile + rcases hvalidate : validateCompileInputs model selectors with _ | validated + · simp [hvalidate] at hcompile + · simp [hvalidate] at hcompile + unfold compileValidatedCore at hcompile + rw [hSupported.normalizedFields, hfallback, hreceive, + contractUsesPlainArrayElement, contractUsesArrayElementWord, harray, + hstorageArray, hdynamicBytesEq, hnoInternalFns, hSupported.noAdtTypes] at hcompile + simp only [bind, Except.bind, pure, Except.pure, List.mapM_nil] at hcompile + rcases hmap : + ((model.functions.filter + (fun fn => !fn.isInternal && !isInteropEntrypointName fn.name)).zip selectors).mapM + (fun x => compileFunctionSpec model.fields model.events model.errors [] x.2 x.1) with _ | irFns + · simp [hmap] at hcompile + · rcases hctor : + compileConstructor model.fields model.events model.errors [] model.constructor with _ | deployStmts + · simp [hmap, hctor] at hcompile + cases hcompile + · simp [hmap, hctor] at hcompile + injection hcompile with hir + cases hir + rfl + -- NOTE: compileValidatedCore_ok_yields_supportedRuntimeHelperTableInterface and -- compile_ok_yields_supportedRuntimeHelperTableInterface are BLOCKED by missing -- DirectInternalHelperPerCalleeCompileCatalog infrastructure in GenericInduction.lean. diff --git a/Compiler/Proofs/IRGeneration/ContractFeatureTest.lean b/Compiler/Proofs/IRGeneration/ContractFeatureTest.lean index 4509c9c15..5321d4abd 100644 --- a/Compiler/Proofs/IRGeneration/ContractFeatureTest.lean +++ b/Compiler/Proofs/IRGeneration/ContractFeatureTest.lean @@ -57,7 +57,8 @@ private def literalMappingWrite_supported_function : supported := by intro param hparam rcases (by simpa [literalMappingWriteFunction] using hparam : param = { name := "value", ty := .uint256 }) with rfl - trivial } + trivial + calldataThreshold := by decide } returns := { resolved := ⟨[], rfl, trivial⟩ } body := { stmtList := @@ -159,7 +160,8 @@ private def constructorOnlySupported : intro param hparam simp [constructorOnlyCtor] at hparam rcases hparam with rfl - trivial } + trivial + calldataThreshold := by decide } body := { stmtList := .append diff --git a/Compiler/Proofs/IRGeneration/ContractShape.lean b/Compiler/Proofs/IRGeneration/ContractShape.lean new file mode 100644 index 000000000..1386e2cd7 --- /dev/null +++ b/Compiler/Proofs/IRGeneration/ContractShape.lean @@ -0,0 +1,395 @@ +import Compiler.Proofs.IRGeneration.SourceSemantics + +set_option linter.unnecessarySimpa false + +namespace Compiler.Proofs.IRGeneration + +open Compiler +open Compiler.CompilationModel + +namespace ContractShape + +private theorem pickUniqueFunctionByName_eq_ok_none_of_absent + (name : String) (funcs : List FunctionSpec) + (habsent : ∀ fn ∈ funcs, fn.name != name) : + pickUniqueFunctionByName name funcs = Except.ok none := by + induction funcs with + | nil => + rfl + | cons fn rest ih => + have hfn : (fn.name == name) = false := by + by_cases heq : fn.name = name + · have habs := habsent fn (by simp) + simp [heq] at habs + · simp [heq] + have hrest : ∀ fn' ∈ rest, fn'.name != name := by + intro fn' hmem + exact habsent fn' (by simp [hmem]) + have ih' := ih hrest + simpa [pickUniqueFunctionByName, hfn] using ih' + +private theorem compiled_functions_forall₂_of_mapM_ok + (fields : List Field) + (events : List EventDef) + (errors : List ErrorDef) : + ∀ (entries : List (FunctionSpec × Nat)) irFns, + (entries.mapM fun (entry : FunctionSpec × Nat) => + compileFunctionSpec fields events errors [] entry.2 entry.1) = Except.ok irFns → + List.Forall₂ + (fun (entry : FunctionSpec × Nat) irFn => + compileFunctionSpec fields events errors [] entry.2 entry.1 = Except.ok irFn) + entries irFns := by + intro entries + induction entries with + | nil => + intro irFns hmap + cases hmap + simp + | cons entry entries ih => + intro irFns hmap + rcases hstep : compileFunctionSpec fields events errors [] entry.2 entry.1 with _ | irFn + · simp only [List.mapM_cons, hstep, bind, Except.bind] at hmap + cases hmap + · rcases htail : List.mapM + (fun (entry : FunctionSpec × Nat) => + compileFunctionSpec fields events errors [] entry.2 entry.1) entries with _ | irFnsTail + · simp only [List.mapM_cons, hstep, htail, bind, Except.bind] at hmap + cases hmap + · simp only [List.mapM_cons, hstep, htail, bind, Except.bind] at hmap + cases hmap + exact List.Forall₂.cons hstep (ih _ htail) + +private theorem compileValidatedCore_ok_yields_compiled_functions + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcore : compileValidatedCore model selectors = Except.ok ir) : + List.Forall₂ + (fun entry irFn => + compileFunctionSpec model.fields model.events model.errors [] entry.2 entry.1 = Except.ok irFn) + (SourceSemantics.selectorFunctionPairs model selectors) + ir.functions := by + have hfallback : + pickUniqueFunctionByName "fallback" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "fallback" model.functions hSupported.noFallback + have hreceive : + pickUniqueFunctionByName "receive" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "receive" model.functions hSupported.noReceive + unfold compileValidatedCore at hcore + rw [hSupported.normalizedFields, + hSupported.noAdtTypes, hSupported.noEvents, hSupported.noErrors, + hfallback, hreceive] at hcore + simp only [bind, Except.bind, pure, Except.pure] at hcore + rcases hmap : + ((model.functions.filter + (fun fn => !fn.isInternal && !isInteropEntrypointName fn.name)).zip selectors).mapM + (fun x => compileFunctionSpec model.fields [] [] [] x.2 x.1) with _ | irFns + · simp [hmap] at hcore + · simp [hmap] at hcore + rcases hinternal : + (model.functions.filter (·.isInternal)).mapM + (compileInternalFunction model.fields [] [] []) with _ | internalFuncDefs + · simp [hinternal] at hcore + · rcases hctor : + compileConstructor model.fields [] [] [] model.constructor with _ | deployStmts + · simp [hinternal, hctor] at hcore + cases hcore + · simp [hinternal, hctor] at hcore + have hfunctions : ir.functions = irFns := by + injection hcore with hir + cases hir + rfl + have hcompiled : + List.Forall₂ + (fun (entry : FunctionSpec × Nat) irFn => + compileFunctionSpec model.fields model.events model.errors [] entry.2 entry.1 = Except.ok irFn) + ((model.functions.filter + (fun fn => !fn.isInternal && !isInteropEntrypointName fn.name)).zip selectors) + irFns := + by + simpa [hSupported.noEvents, hSupported.noErrors] using + (compiled_functions_forall₂_of_mapM_ok model.fields [] [] _ _ hmap) + simpa [SourceSemantics.selectorFunctionPairs, selectorDispatchedFunctions, + hfunctions] using hcompiled + +private theorem filterInternalFunctions_eq_nil_of_all_nonInternal : + ∀ (fns : List FunctionSpec), + (∀ fn ∈ fns, fn.isInternal = false) → + fns.filter (·.isInternal) = [] + | [], _ => rfl + | fn :: rest, hall => by + have hfn : fn.isInternal = false := hall fn (by simp) + have hrest : ∀ fn' ∈ rest, fn'.isInternal = false := by + intro fn' hmem + exact hall fn' (by simp [hmem]) + simp [hfn, filterInternalFunctions_eq_nil_of_all_nonInternal rest hrest] + +private theorem filterInternalFunctions_eq_nil_of_supported + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) : + model.functions.filter (·.isInternal) = [] := by + exact filterInternalFunctions_eq_nil_of_all_nonInternal model.functions + (hSupported.noInternalFunctions) + +private theorem compileValidatedCore_ok_yields_internalFunctions_nil + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcore : compileValidatedCore model selectors = Except.ok ir) : + ir.internalFunctions = [] := by + have hfallback : + pickUniqueFunctionByName "fallback" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "fallback" model.functions hSupported.noFallback + have hreceive : + pickUniqueFunctionByName "receive" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "receive" model.functions hSupported.noReceive + have hnoInternalFns : + model.functions.filter (·.isInternal) = [] := + filterInternalFunctions_eq_nil_of_supported model selectors hSupported + have harray : contractUsesArrayElement model = false := + hSupported.contractUsesArrayElement_eq_false + have hstorageArray : contractUsesStorageArrayElement model = false := + hSupported.contractUsesStorageArrayElement_eq_false + have hdynamicBytesEq : contractUsesDynamicBytesEq model = false := + hSupported.contractUsesDynamicBytesEq_eq_false + unfold compileValidatedCore at hcore + rw [hSupported.normalizedFields, hfallback, hreceive, + contractUsesPlainArrayElement, contractUsesArrayElementWord, harray, + hstorageArray, hdynamicBytesEq, hnoInternalFns, hSupported.noAdtTypes] at hcore + simp only [bind, Except.bind, pure, Except.pure, List.mapM_nil] at hcore + rcases hmap : + ((model.functions.filter + (fun fn => !fn.isInternal && !isInteropEntrypointName fn.name)).zip selectors).mapM + (fun x => compileFunctionSpec model.fields model.events model.errors [] x.2 x.1) with _ | irFns + · simp [hmap] at hcore + · rcases hctor : + compileConstructor model.fields model.events model.errors [] model.constructor with _ | deployStmts + · simp [hmap, hctor] at hcore + cases hcore + · simp [hmap, hctor] at hcore + cases hcore + rfl + +private theorem compileValidatedCore_ok_yields_deploy_compileConstructor + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcore : compileValidatedCore model selectors = Except.ok ir) : + compileConstructor model.fields model.events model.errors [] model.constructor = + Except.ok ir.deploy := by + have hfallback : + pickUniqueFunctionByName "fallback" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "fallback" model.functions hSupported.noFallback + have hreceive : + pickUniqueFunctionByName "receive" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "receive" model.functions hSupported.noReceive + unfold compileValidatedCore at hcore + rw [hSupported.normalizedFields, + hSupported.noAdtTypes, hSupported.noEvents, hSupported.noErrors, + hfallback, hreceive] at hcore + simp only [bind, Except.bind, pure, Except.pure] at hcore + rcases hmap : + ((model.functions.filter + (fun fn => !fn.isInternal && !isInteropEntrypointName fn.name)).zip selectors).mapM + (fun x => compileFunctionSpec model.fields [] [] [] x.2 x.1) with _ | irFns + · simp [hmap] at hcore + · simp [hmap] at hcore + rcases hinternal : + (model.functions.filter (·.isInternal)).mapM + (compileInternalFunction model.fields [] [] []) with _ | internalFuncDefs + · simp [hinternal] at hcore + · rcases hctor : + compileConstructor model.fields [] [] [] model.constructor with _ | deployStmts + · simp [hinternal, hctor] at hcore + cases hcore + · simp [hinternal, hctor] at hcore + cases hcore + simpa [hSupported.noEvents, hSupported.noErrors] using hctor + +private theorem compileValidatedCore_ok_yields_noFallbackEntrypoint + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcore : compileValidatedCore model selectors = Except.ok ir) : + ir.fallbackEntrypoint = none := by + have hfallback : + pickUniqueFunctionByName "fallback" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "fallback" model.functions hSupported.noFallback + have hreceive : + pickUniqueFunctionByName "receive" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "receive" model.functions hSupported.noReceive + unfold compileValidatedCore at hcore + rw [hfallback, hreceive] at hcore + simp only [bind, Except.bind, Option.mapM_none, pure, Except.pure] at hcore + rcases hmap : + ((model.functions.filter + (fun fn => !fn.isInternal && !isInteropEntrypointName fn.name)).zip selectors).mapM + (fun x => compileFunctionSpec (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes x.2 x.1) with _ | irFns + · simp [hmap] at hcore + · rcases hinternal : + (model.functions.filter (·.isInternal)).mapM + (compileInternalFunction (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes) with _ | internalFuncDefs + · simp [hmap, hinternal] at hcore + · rcases hctor : + compileConstructor (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes model.constructor with _ | deployStmts + · simp [hmap, hinternal, hctor] at hcore + · simp [hmap, hinternal, hctor] at hcore + cases hcore + rfl + +private theorem compileValidatedCore_ok_yields_noReceiveEntrypoint + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcore : compileValidatedCore model selectors = Except.ok ir) : + ir.receiveEntrypoint = none := by + have hfallback : + pickUniqueFunctionByName "fallback" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "fallback" model.functions hSupported.noFallback + have hreceive : + pickUniqueFunctionByName "receive" model.functions = Except.ok none := + pickUniqueFunctionByName_eq_ok_none_of_absent + "receive" model.functions hSupported.noReceive + unfold compileValidatedCore at hcore + rw [hfallback, hreceive] at hcore + simp only [bind, Except.bind, Option.mapM_none, pure, Except.pure] at hcore + rcases hmap : + ((model.functions.filter + (fun fn => !fn.isInternal && !isInteropEntrypointName fn.name)).zip selectors).mapM + (fun x => compileFunctionSpec (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes x.2 x.1) with _ | irFns + · simp [hmap] at hcore + · rcases hinternal : + (model.functions.filter (·.isInternal)).mapM + (compileInternalFunction (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes) with _ | internalFuncDefs + · simp [hmap, hinternal] at hcore + · rcases hctor : + compileConstructor (applySlotAliasRanges model.fields model.slotAliasRanges) + model.events model.errors model.adtTypes model.constructor with _ | deployStmts + · simp [hmap, hinternal, hctor] at hcore + · simp [hmap, hinternal, hctor] at hcore + cases hcore + rfl + +theorem compile_ok_yields_compiled_functions + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcompile : CompilationModel.compile model selectors = Except.ok ir) : + List.Forall₂ + (fun entry irFn => + compileFunctionSpec model.fields model.events model.errors [] entry.2 entry.1 = Except.ok irFn) + (SourceSemantics.selectorFunctionPairs model selectors) + ir.functions := by + unfold CompilationModel.compile at hcompile + simp only [bind, Except.bind] at hcompile + rcases hvalidate : validateCompileInputs model selectors with _ | validated + · simp [hvalidate] at hcompile + · simp [hvalidate] at hcompile + exact compileValidatedCore_ok_yields_compiled_functions + (model := model) + (selectors := selectors) + (hSupported := hSupported) + (ir := ir) + (hcore := hcompile) + +theorem compile_ok_yields_internalFunctions_nil + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcompile : CompilationModel.compile model selectors = Except.ok ir) : + ir.internalFunctions = [] := by + unfold CompilationModel.compile at hcompile + simp only [bind, Except.bind] at hcompile + rcases hvalidate : validateCompileInputs model selectors with _ | validated + · simp [hvalidate] at hcompile + · simp [hvalidate] at hcompile + exact compileValidatedCore_ok_yields_internalFunctions_nil + (model := model) + (selectors := selectors) + (hSupported := hSupported) + (ir := ir) + (hcore := hcompile) + +theorem compile_ok_yields_deploy_compileConstructor + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcompile : CompilationModel.compile model selectors = Except.ok ir) : + compileConstructor model.fields model.events model.errors [] model.constructor = + Except.ok ir.deploy := by + unfold CompilationModel.compile at hcompile + simp only [bind, Except.bind] at hcompile + rcases hvalidate : validateCompileInputs model selectors with _ | validated + · simp [hvalidate] at hcompile + · simp [hvalidate] at hcompile + exact compileValidatedCore_ok_yields_deploy_compileConstructor + (model := model) + (selectors := selectors) + (hSupported := hSupported) + (ir := ir) + (hcore := hcompile) + +theorem compile_ok_yields_noFallbackEntrypoint + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcompile : CompilationModel.compile model selectors = Except.ok ir) : + ir.fallbackEntrypoint = none := by + unfold CompilationModel.compile at hcompile + simp only [bind, Except.bind] at hcompile + rcases hvalidate : validateCompileInputs model selectors with _ | validated + · simp [hvalidate] at hcompile + · simp [hvalidate] at hcompile + exact compileValidatedCore_ok_yields_noFallbackEntrypoint + (model := model) + (selectors := selectors) + (hSupported := hSupported) + (ir := ir) + (hcore := hcompile) + +theorem compile_ok_yields_noReceiveEntrypoint + (model : CompilationModel) + (selectors : List Nat) + (hSupported : SupportedSpec model selectors) + (ir : IRContract) + (hcompile : CompilationModel.compile model selectors = Except.ok ir) : + ir.receiveEntrypoint = none := by + unfold CompilationModel.compile at hcompile + simp only [bind, Except.bind] at hcompile + rcases hvalidate : validateCompileInputs model selectors with _ | validated + · simp [hvalidate] at hcompile + · simp [hvalidate] at hcompile + exact compileValidatedCore_ok_yields_noReceiveEntrypoint + (model := model) + (selectors := selectors) + (hSupported := hSupported) + (ir := ir) + (hcore := hcompile) + +end ContractShape + +end Compiler.Proofs.IRGeneration diff --git a/Compiler/Proofs/IRGeneration/Dispatch.lean b/Compiler/Proofs/IRGeneration/Dispatch.lean index 22279d683..cf540bd3e 100644 --- a/Compiler/Proofs/IRGeneration/Dispatch.lean +++ b/Compiler/Proofs/IRGeneration/Dispatch.lean @@ -173,7 +173,14 @@ theorem interpretContract_correct_of_compiled_functions (FunctionBody.initialIRStateForTx model tx initialWorld) = match irFns.find? (fun irFn => irFn.selector == tx.functionSelector) with | some irFn => - if irFn.params.length ≤ tx.args.length then + if !irFn.payable && tx.msgValue % Compiler.Constants.evmModulus != 0 then + { success := false + returnValue := none + finalStorage := (FunctionBody.initialIRStateForTx model tx initialWorld).storage + finalMappings := Compiler.Proofs.storageAsMappings + (FunctionBody.initialIRStateForTx model tx initialWorld).storage + events := (FunctionBody.initialIRStateForTx model tx initialWorld).events } + else if irFn.params.length ≤ tx.args.length then execIRFunction irFn tx.args (FunctionBody.initialIRStateForTx model tx initialWorld) else { success := false @@ -217,28 +224,49 @@ theorem interpretContract_correct_of_compiled_functions model.fields model.events model.errors sel fn irFn hcompileFn have hlenEq : irFn.params.length = fn.params.length := by simpa [hparamsEq] - by_cases hlen : fn.params.length ≤ tx.args.length - · rcases bindSupportedParams_some_of_supported fn.params tx.args - (hparamsSupported fn hfnMem) hlen with ⟨bindings, hbindings⟩ - have hmatch := hfunction fn sel irFn bindings hfnMem hcompileFn hbindings - have hlenIr : irFn.params.length ≤ tx.args.length := by - simpa [hlenEq] using hlen - rw [hinterp, hfindIr] - simpa [hfindPairs, hlenIr] using hmatch - · have hbindNone : SourceSemantics.bindSupportedParams fn.params tx.args = none := by - cases hbind : SourceSemantics.bindSupportedParams fn.params tx.args with - | none => - rfl - | some bindings => - exfalso - exact hlen (ParamLoading.bindSupportedParams_some_length hbind) - have hlenIr : ¬ irFn.params.length ≤ tx.args.length := by - simpa [hlenEq] using hlen + have hpayableEq : + irFn.payable = fn.isPayable := + Function.compileFunctionSpec_ok_payable + model.fields model.events model.errors sel fn irFn hcompileFn + by_cases hguard : (!fn.isPayable && tx.msgValue % Compiler.Constants.evmModulus != 0) = true + · have hguardIr : + (!irFn.payable && tx.msgValue % Compiler.Constants.evmModulus != 0) = true := by + simpa [hpayableEq] using hguard rw [hinterp, hfindIr] - simp [SourceSemantics.interpretFunction, hbindNone, hlenIr, - FunctionBody.sourceResultMatchesIRResult, SourceSemantics.revertedResult, - FunctionBody.initialIRStateForTx, FunctionBody.encodeStorage_withTransactionContext, + simp [hfindPairs, hguard, hguardIr, FunctionBody.sourceResultMatchesIRResult, + SourceSemantics.revertedResult, FunctionBody.initialIRStateForTx, + FunctionBody.encodeStorage_withTransactionContext, FunctionBody.encodeEvents_withTransactionContext] + · + have hguardFalse : + (!fn.isPayable && tx.msgValue % Compiler.Constants.evmModulus != 0) = false := + Bool.eq_false_iff.2 hguard + have hguardIrFalse : + (!irFn.payable && tx.msgValue % Compiler.Constants.evmModulus != 0) = false := by + simpa [hpayableEq] using hguardFalse + by_cases hlen : fn.params.length ≤ tx.args.length + · rcases bindSupportedParams_some_of_supported fn.params tx.args + (hparamsSupported fn hfnMem) hlen with ⟨bindings, hbindings⟩ + have hmatch := hfunction fn sel irFn bindings hfnMem hcompileFn hbindings + have hlenIr : irFn.params.length ≤ tx.args.length := by + simpa [hlenEq] using hlen + rw [hinterp, hfindIr] + simpa [hfindPairs, hguardFalse, hguardIrFalse, hlenIr] using hmatch + · have hbindNone : SourceSemantics.bindSupportedParams fn.params tx.args = none := by + cases hbind : SourceSemantics.bindSupportedParams fn.params tx.args with + | none => + rfl + | some bindings => + exfalso + exact hlen (ParamLoading.bindSupportedParams_some_length hbind) + have hlenIr : ¬ irFn.params.length ≤ tx.args.length := by + simpa [hlenEq] using hlen + rw [hinterp, hfindIr] + simp [SourceSemantics.interpretFunction, hbindNone, hfindPairs, hguardFalse, + hguardIrFalse, hlenIr, FunctionBody.sourceResultMatchesIRResult, + SourceSemantics.revertedResult, FunctionBody.initialIRStateForTx, + FunctionBody.encodeStorage_withTransactionContext, + FunctionBody.encodeEvents_withTransactionContext] /-- Helper-proof-carrying wrapper for the dispatch theorem. The current proof still reduces helper-aware source semantics to the legacy diff --git a/Compiler/Proofs/IRGeneration/Function.lean b/Compiler/Proofs/IRGeneration/Function.lean index 11c24e045..bee9f80ea 100644 --- a/Compiler/Proofs/IRGeneration/Function.lean +++ b/Compiler/Proofs/IRGeneration/Function.lean @@ -4,7 +4,7 @@ import Compiler.Proofs.IRGeneration.GenericInduction import Compiler.Proofs.IRGeneration.ParamLoading import Compiler.Proofs.IRGeneration.SourceSemantics import Compiler.Proofs.IRGeneration.SupportedSpec -import Compiler.Proofs.YulGeneration.Equivalence +import Compiler.Proofs.YulGeneration.IRFuel set_option linter.unnecessarySeqFocus false set_option linter.unnecessarySimpa false @@ -238,6 +238,30 @@ theorem compileFunctionSpec_ok_selector injection hcompile with hEq simpa using congrArg IRFunction.selector hEq.symm +theorem compileFunctionSpec_ok_payable + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (selector : Nat) (spec : FunctionSpec) (irFn : IRFunction) + (hcompile : compileFunctionSpec fields events errors [] selector spec = Except.ok irFn) : + irFn.payable = spec.isPayable := by + unfold CompilationModel.compileFunctionSpec at hcompile + cases hvalidate : validateFunctionSpec spec + · rw [hvalidate] at hcompile + cases hcompile + case ok _ => + cases hreturns : functionReturns spec + · rw [hvalidate, hreturns] at hcompile + cases hcompile + case ok returns => + cases hbody : + compileStmtList fields events errors .calldata [] false + (spec.params.map (·.name)) [] spec.body + · rw [hvalidate, hreturns, hbody] at hcompile + cases hcompile + case ok bodyStmts => + rw [hvalidate, hreturns, hbody] at hcompile + injection hcompile with hEq + simpa using congrArg IRFunction.payable hEq.symm + theorem compileFunctionSpec_ok_components (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (selector : Nat) (spec : FunctionSpec) (irFn : IRFunction) diff --git a/Compiler/Proofs/IRGeneration/FunctionBody.lean b/Compiler/Proofs/IRGeneration/FunctionBody.lean index d939d8148..b0d542e5c 100644 --- a/Compiler/Proofs/IRGeneration/FunctionBody.lean +++ b/Compiler/Proofs/IRGeneration/FunctionBody.lean @@ -207,8 +207,8 @@ theorem evalIRExpr_caller_of_runtimeStateMatchesIR evalIRExpr state (YulExpr.call "caller" []) = some (SourceSemantics.evalExpr fields runtime (.caller)) := by rcases hmatch with ⟨_, _, hsender, _, _, _, _, _, _, _, _, _⟩ - simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, hsender] + simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, hsender] rfl theorem evalIRExpr_contractAddress_of_runtimeStateMatchesIR @@ -226,8 +226,8 @@ theorem evalIRExpr_contractAddress_of_runtimeStateMatchesIR omega have hthisMod : runtime.world.thisAddress.val % Compiler.Constants.evmModulus = runtime.world.thisAddress.val := Nat.mod_eq_of_lt hthisLt - simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, hthisAddress, hthisMod] + simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, hthisAddress, hthisMod] rfl theorem evalIRExpr_msgValue_of_runtimeStateMatchesIR @@ -242,8 +242,8 @@ theorem evalIRExpr_msgValue_of_runtimeStateMatchesIR simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using runtime.world.msgValue.isLt have hmsgMod : runtime.world.msgValue.val % Compiler.Constants.evmModulus = runtime.world.msgValue.val := Nat.mod_eq_of_lt hmsgLt - simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, hmsgValue, hmsgMod] + simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, hmsgValue, hmsgMod] rfl theorem evalIRExpr_blockTimestamp_of_runtimeStateMatchesIR @@ -258,8 +258,8 @@ theorem evalIRExpr_blockTimestamp_of_runtimeStateMatchesIR simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using runtime.world.blockTimestamp.isLt have htimeMod : runtime.world.blockTimestamp.val % Compiler.Constants.evmModulus = runtime.world.blockTimestamp.val := Nat.mod_eq_of_lt htimeLt - simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, hblockTimestamp, htimeMod] + simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, hblockTimestamp, htimeMod] rfl theorem evalIRExpr_blockNumber_of_runtimeStateMatchesIR @@ -274,8 +274,8 @@ theorem evalIRExpr_blockNumber_of_runtimeStateMatchesIR simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using runtime.world.blockNumber.isLt have hnumberMod : runtime.world.blockNumber.val % Compiler.Constants.evmModulus = runtime.world.blockNumber.val := Nat.mod_eq_of_lt hnumberLt - simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, hblockNumber, hnumberMod] + simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, hblockNumber, hnumberMod] rfl theorem evalIRExpr_chainid_of_runtimeStateMatchesIR @@ -290,8 +290,8 @@ theorem evalIRExpr_chainid_of_runtimeStateMatchesIR simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using runtime.world.chainId.isLt have hchainMod : runtime.world.chainId.val % Compiler.Constants.evmModulus = runtime.world.chainId.val := Nat.mod_eq_of_lt hchainLt - simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, hchainId, hchainMod] + simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, hchainId, hchainMod] rfl theorem evalIRExpr_blobbasefee_of_runtimeStateMatchesIR @@ -306,8 +306,8 @@ theorem evalIRExpr_blobbasefee_of_runtimeStateMatchesIR simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using runtime.world.blobBaseFee.isLt have hblobMod : runtime.world.blobBaseFee.val % Compiler.Constants.evmModulus = runtime.world.blobBaseFee.val := Nat.mod_eq_of_lt hblobLt - simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, hblobBaseFee, hblobMod] + simp [evalIRExpr, evalIRCall, evalIRExprs, Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, hblobBaseFee, hblobMod] rfl theorem eval_compileExpr_caller @@ -397,8 +397,8 @@ theorem evalIRExpr_calldatasize_of_runtimeStateMatchesIR exact Nat.mod_eq_of_lt runtime.world.calldataSize.isLt rw [heval] simp [evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, hcalldataSizeMod] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, hcalldataSizeMod] theorem eval_compileExpr_calldatasize {fields : List Field} @@ -437,13 +437,13 @@ theorem evalIRExpr_iszero_of_lt by_cases hzero : value = 0 · subst hzero simp [evalIRExpr, evalIRCall, evalIRExprs, heval, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, SourceSemantics.boolWord] · have hmod : value % Compiler.Constants.evmModulus = value := Nat.mod_eq_of_lt hvalueLt simp [evalIRExpr, evalIRCall, evalIRExprs, heval, hmod, hzero, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, SourceSemantics.boolWord] theorem evalIRExpr_yulToBool_of_lt @@ -457,13 +457,13 @@ theorem evalIRExpr_yulToBool_of_lt by_cases hzero : value = 0 · subst hzero simp [CompilationModel.yulToBool, evalIRExpr, evalIRCall, evalIRExprs, heval, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, SourceSemantics.boolWord] · have hmod : value % Compiler.Constants.evmModulus = value := Nat.mod_eq_of_lt hvalueLt simp [CompilationModel.yulToBool, evalIRExpr, evalIRCall, evalIRExprs, heval, hmod, hzero, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, SourceSemantics.boolWord] theorem evalIRExpr_add_of_eval @@ -475,8 +475,8 @@ theorem evalIRExpr_add_of_eval evalIRExpr state (YulExpr.call "add" [lhs, rhs]) = some ((a + b) % Compiler.Constants.evmModulus) := by simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] theorem evalIRExpr_sub_of_eval {state : IRState} @@ -488,8 +488,8 @@ theorem evalIRExpr_sub_of_eval some ((Compiler.Constants.evmModulus + (a % Compiler.Constants.evmModulus) - (b % Compiler.Constants.evmModulus)) % Compiler.Constants.evmModulus) := by simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] theorem evalIRExpr_mul_of_eval {state : IRState} @@ -500,8 +500,8 @@ theorem evalIRExpr_mul_of_eval evalIRExpr state (YulExpr.call "mul" [lhs, rhs]) = some ((a * b) % Compiler.Constants.evmModulus) := by simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] theorem evalIRExpr_div_of_eval {state : IRState} @@ -514,11 +514,11 @@ theorem evalIRExpr_div_of_eval (a % Compiler.Constants.evmModulus) / (b % Compiler.Constants.evmModulus)) := by by_cases hzero : b % Compiler.Constants.evmModulus = 0 · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hzero, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hzero, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] theorem evalIRExpr_mod_of_eval {state : IRState} @@ -531,11 +531,11 @@ theorem evalIRExpr_mod_of_eval (a % Compiler.Constants.evmModulus) % (b % Compiler.Constants.evmModulus)) := by by_cases hzero : b % Compiler.Constants.evmModulus = 0 · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hzero, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hzero, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] theorem evalIRExpr_eq_of_eval {state : IRState} @@ -548,12 +548,12 @@ theorem evalIRExpr_eq_of_eval b % Compiler.Constants.evmModulus)) := by by_cases heq : a % Compiler.Constants.evmModulus = b % Compiler.Constants.evmModulus · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, heq, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, SourceSemantics.boolWord] · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, heq, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, SourceSemantics.boolWord] theorem evalIRExpr_lt_of_eval @@ -567,12 +567,12 @@ theorem evalIRExpr_lt_of_eval b % Compiler.Constants.evmModulus)) := by by_cases hlt : a % Compiler.Constants.evmModulus < b % Compiler.Constants.evmModulus · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hlt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, SourceSemantics.boolWord] · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hlt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, SourceSemantics.boolWord] theorem evalIRExpr_gt_of_eval @@ -588,14 +588,14 @@ theorem evalIRExpr_gt_of_eval · have hcmp : ¬ a % Compiler.Constants.evmModulus ≤ b % Compiler.Constants.evmModulus := by exact Nat.not_le_of_gt hgt simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hgt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, SourceSemantics.boolWord] · have hcmp : a % Compiler.Constants.evmModulus ≤ b % Compiler.Constants.evmModulus := by exact Nat.le_of_not_gt hgt simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hgt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, SourceSemantics.boolWord] theorem evalIRExpr_slt_of_eval @@ -611,13 +611,13 @@ theorem evalIRExpr_slt_of_eval by_cases hslt : (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus)) : Int) < (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus)) : Int) · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hslt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Verity.Core.Int256.toInt, SourceSemantics.boolWord] · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hslt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Verity.Core.Int256.toInt, SourceSemantics.boolWord] @@ -634,13 +634,13 @@ theorem evalIRExpr_sgt_of_eval by_cases hsgt : (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus)) : Int) < (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus)) : Int) · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hsgt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Verity.Core.Int256.toInt, SourceSemantics.boolWord] · simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, hsgt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Verity.Core.Int256.toInt, SourceSemantics.boolWord] @@ -655,8 +655,8 @@ theorem evalIRExpr_sdiv_of_eval (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus)))).toUint256.val := by simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Verity.Core.Int256.toUint256] theorem evalIRExpr_smod_of_eval @@ -670,8 +670,8 @@ theorem evalIRExpr_smod_of_eval (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus)))).toUint256.val := by simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Verity.Core.Int256.toUint256] theorem evalIRExpr_sar_of_eval @@ -685,8 +685,8 @@ theorem evalIRExpr_sar_of_eval (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus)))).toUint256.val := by simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Verity.Core.Int256.toUint256] theorem evalIRExpr_signextend_of_eval @@ -700,8 +700,8 @@ theorem evalIRExpr_signextend_of_eval (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus)) (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus))).val := by simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Verity.Core.Uint256.signextend] theorem evalIRExpr_and_of_eval @@ -713,8 +713,8 @@ theorem evalIRExpr_and_of_eval evalIRExpr state (YulExpr.call "and" [lhs, rhs]) = some ((a % Compiler.Constants.evmModulus) &&& (b % Compiler.Constants.evmModulus)) := by simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] theorem evalIRExpr_or_of_eval {state : IRState} @@ -725,8 +725,8 @@ theorem evalIRExpr_or_of_eval evalIRExpr state (YulExpr.call "or" [lhs, rhs]) = some ((a % Compiler.Constants.evmModulus) ||| (b % Compiler.Constants.evmModulus)) := by simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] theorem evalIRExpr_xor_of_eval {state : IRState} @@ -737,8 +737,8 @@ theorem evalIRExpr_xor_of_eval evalIRExpr state (YulExpr.call "xor" [lhs, rhs]) = some (Nat.xor (a % Compiler.Constants.evmModulus) (b % Compiler.Constants.evmModulus)) := by simp [evalIRExpr, evalIRCall, evalIRExprs, hlhs, hrhs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] theorem evalIRExpr_not_of_eval {state : IRState} @@ -749,8 +749,8 @@ theorem evalIRExpr_not_of_eval some (Nat.xor (value % Compiler.Constants.evmModulus) (Compiler.Constants.evmModulus - 1)) := by simp [evalIRExpr, evalIRCall, evalIRExprs, heval, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] theorem evalIRExpr_shl_of_eval {state : IRState} @@ -766,11 +766,11 @@ theorem evalIRExpr_shl_of_eval 0) := by by_cases hlt : shift % Compiler.Constants.evmModulus < 256 · simp [evalIRExpr, evalIRCall, evalIRExprs, hshift, hvalue, hlt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] · simp [evalIRExpr, evalIRCall, evalIRExprs, hshift, hvalue, hlt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] theorem evalIRExpr_shr_of_eval {state : IRState} @@ -786,11 +786,11 @@ theorem evalIRExpr_shr_of_eval 0) := by by_cases hlt : shift % Compiler.Constants.evmModulus < 256 · simp [evalIRExpr, evalIRCall, evalIRExprs, hshift, hvalue, hlt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] · simp [evalIRExpr, evalIRCall, evalIRExprs, hshift, hvalue, hlt, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] private theorem findEntry_filter_ne_eq_findEntry (entries : List (String × Nat)) @@ -1234,8 +1234,8 @@ theorem evalIRExpr_sload_of_runtimeStateMatchesIR % EvmYul.UInt256.size) := by rcases hmatch with ⟨hstorage, _, _, _, _, _, _, _, _, _, _⟩ simp [evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, hstorage] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, hstorage] theorem eval_compileExpr_param_of_exact_bindings {fields : List Field} @@ -11026,8 +11026,8 @@ private theorem evalIRExpr_compiled_terminal_ite_elseCond_of_zero evalIRExpr (state.setVar tempName condValue) (YulExpr.call "iszero" [YulExpr.ident tempName]) = some 1 := by simp [evalIRExpr, evalIRCall, evalIRExprs, hcondZero, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] /-- Entering the taken `then` branch of a compiled terminal `ite` re-expresses the remaining fuel in the branch-local schema expected by recursive body diff --git a/Compiler/Proofs/IRGeneration/FunctionShape.lean b/Compiler/Proofs/IRGeneration/FunctionShape.lean new file mode 100644 index 000000000..f06e7adca --- /dev/null +++ b/Compiler/Proofs/IRGeneration/FunctionShape.lean @@ -0,0 +1,55 @@ +import Compiler.CompilationModel.Dispatch + +namespace Compiler.Proofs.IRGeneration + +open Compiler +open Compiler.CompilationModel +open Compiler.Yul + +namespace FunctionShape + +def compiledFunctionIR + (selector : Nat) (spec : FunctionSpec) (returns : List ParamType) (bodyStmts : List YulStmt) : + IRFunction := + { name := spec.name + selector := selector + params := spec.params.map Param.toIRParam + ret := match returns with + | [single] => single.toIRType + | _ => IRType.unit + payable := spec.isPayable + body := genParamLoads spec.params ++ bodyStmts } + +theorem compileFunctionSpec_ok_components + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (selector : Nat) (spec : FunctionSpec) (irFn : IRFunction) + (hcompile : compileFunctionSpec fields events errors [] selector spec = Except.ok irFn) : + ∃ returns bodyStmts, + validateFunctionSpec spec = Except.ok () ∧ + functionReturns spec = Except.ok returns ∧ + compileStmtList fields events errors .calldata [] false + (spec.params.map (·.name)) [] spec.body = Except.ok bodyStmts ∧ + irFn = compiledFunctionIR selector spec returns bodyStmts := by + unfold CompilationModel.compileFunctionSpec at hcompile + cases hvalidate : validateFunctionSpec spec + · rw [hvalidate] at hcompile + cases hcompile + case ok _ => + cases hreturns : functionReturns spec + · rw [hvalidate, hreturns] at hcompile + cases hcompile + case ok returns => + cases hbody : + compileStmtList fields events errors .calldata [] false + (spec.params.map (·.name)) [] spec.body + · rw [hvalidate, hreturns, hbody] at hcompile + cases hcompile + case ok bodyStmts => + rw [hvalidate, hreturns, hbody] at hcompile + injection hcompile with hEq + refine ⟨returns, bodyStmts, ?_⟩ + exact ⟨by simp, by simp, by simp, hEq.symm⟩ + +end FunctionShape + +end Compiler.Proofs.IRGeneration diff --git a/Compiler/Proofs/IRGeneration/GenericInduction.lean b/Compiler/Proofs/IRGeneration/GenericInduction.lean index cfb99342c..1b1f3dbff 100644 --- a/Compiler/Proofs/IRGeneration/GenericInduction.lean +++ b/Compiler/Proofs/IRGeneration/GenericInduction.lean @@ -8474,8 +8474,8 @@ private theorem evalIRExpr_mappingSlotChain evalIRExpr state (YulExpr.call "mappingSlot" [startExpr, exprIR]) = some (Compiler.Proofs.abstractMappingSlot startSlot value) := by simp [evalIRExpr, evalIRCall, evalIRExprs, hstart, hexpr, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] simpa [List.foldl] using ih (startExpr := YulExpr.call "mappingSlot" [startExpr, exprIR]) (startSlot := Compiler.Proofs.abstractMappingSlot startSlot value) hnext @@ -8512,8 +8512,8 @@ private theorem execIRStmt_sstore_of_eval by_cases hfunc : fname = "mappingSlot" · subst hfunc simp only [evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] at hslot + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] at hslot cases hb : evalIRExpr state arg with | none => simp [hb] at hslot | some bv => @@ -8571,8 +8571,8 @@ private theorem execIRStmt_sstore_foldl_mappingSlot (Compiler.Yul.YulExpr.call "mappingSlot" [startExpr, exprIR]) = some (Compiler.Proofs.abstractMappingSlot startSlot keyVal) := by simp [evalIRExpr, evalIRCall, evalIRExprs, hstart, hexpr, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] exact ih (Compiler.Yul.YulExpr.call "mappingSlot" [startExpr, exprIR]) (Compiler.Proofs.abstractMappingSlot startSlot keyVal) hnext @@ -9150,8 +9150,8 @@ private theorem compiledStmtStep_setMappingWord_singleSlot_of_slotSafety_preserv .continue state' := by simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, hIRKey, hIRValue, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Compiler.Proofs.abstractMappingSlot_eq_solidity, state', hTargetMod, hStoreEq] have hIRExec : execIRStmts (1 + extraFuel + 1) state @@ -9616,8 +9616,8 @@ private theorem compiledStmtStep_setMappingPackedWord_singleSlot_of_slotSafety_p have hSlotWordEval : evalIRExpr state2 (YulExpr.call "sload" [writeSlotExpr]) = some oldWordNat := by simp [evalIRExpr, evalIRCall, evalIRExprs, hWriteSlotEval2, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, oldWordNat, state2, state1] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, oldWordNat, state2, state1] set state3 := state2.setVar "__compat_slot_word" oldWordNat have hexact_state3 : FunctionBody.bindingsExactlyMatchIRVarsOnScope scope runtime.bindings state3 := FunctionBody.bindingsExactlyMatchIRVarsOnScope_setVar_irrelevant hexact_state2 hcompatSlotWord @@ -10246,8 +10246,8 @@ private theorem compiledStmtStep_setStructMember_singleSlot_of_slotSafety_preser .continue state' := by simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, hIRKey, hIRValue, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Compiler.Proofs.abstractMappingSlot_eq_solidity, state', hTargetMod, hStoreEq] have hIRExec : execIRStmts (1 + extraFuel + 1) state @@ -10446,8 +10446,8 @@ private theorem compiledStmtStep_setMapping2_singleSlot_of_slotSafety_preserves [YulExpr.call "mappingSlot" [YulExpr.lit slot, key1IR], key2IR], valueIR])) = .continue state' := by simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, hIRKey1, hIRKey2, hIRValue, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Compiler.Proofs.abstractStoreMappingEntry_eq, state'] have hfuelEq : 1 + extraFuel = extraFuel + 1 := by omega have hIRExec : execIRStmts (compiledIR.length + extraFuel + 1) state compiledIR = @@ -10733,8 +10733,8 @@ private theorem compiledStmtStep_setMapping2Word_singleSlot_of_slotSafety_preser key2Nat valueNat } by simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, hIRKey1, hIRKey2, hIRValue, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Compiler.Proofs.abstractStoreMappingEntry_eq]) have hfuelEq : 1 + extraFuel = extraFuel + 1 := by omega have hIRExec : execIRStmts (compiledIR.length + extraFuel + 1) state compiledIR = @@ -10791,8 +10791,8 @@ private theorem compiledStmtStep_setMapping2Word_singleSlot_of_slotSafety_preser .continue state' := by simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, hIRKey1, hIRKey2, hIRValue, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Compiler.Proofs.abstractMappingSlot_eq_solidity, state', hTargetMod, hStoreEq] have hfuelEq : 1 + extraFuel = extraFuel + 1 := by omega @@ -11064,8 +11064,8 @@ private theorem compiledStmtStep_setStructMember2_singleSlot_of_slotSafety_prese key2Nat valueNat } by simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, hIRKey1, hIRKey2, hIRValue, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Compiler.Proofs.abstractStoreMappingEntry_eq]) have hfuelEq : 1 + extraFuel = extraFuel + 1 := by omega have hIRExec : execIRStmts (compiledIR.length + extraFuel + 1) state compiledIR = @@ -11122,8 +11122,8 @@ private theorem compiledStmtStep_setStructMember2_singleSlot_of_slotSafety_prese .continue state' := by simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, hIRKey1, hIRKey2, hIRValue, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Compiler.Proofs.abstractMappingSlot_eq_solidity, state', hTargetMod, hStoreEq] have hfuelEq : 1 + extraFuel = extraFuel + 1 := by omega diff --git a/Compiler/Proofs/IRGeneration/IRInterpreter.lean b/Compiler/Proofs/IRGeneration/IRInterpreter.lean index 7293d8e4c..554044560 100644 --- a/Compiler/Proofs/IRGeneration/IRInterpreter.lean +++ b/Compiler/Proofs/IRGeneration/IRInterpreter.lean @@ -15,9 +15,12 @@ import Compiler.IR import Compiler.CompilationModel +import Compiler.Proofs.IRGeneration.IRRuntimeTypes import Compiler.Proofs.IRGeneration.IRStorageWord import Compiler.Proofs.MappingSlot -import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins +import Compiler.Proofs.YulGeneration.LogNames +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBuiltinSemantics +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanPureBuiltinLemmas import Verity.Core namespace Compiler.Proofs.IRGeneration @@ -27,6 +30,8 @@ open Compiler.Yul open Verity.Core open Compiler.Proofs +export Compiler.Proofs.YulGeneration (isYulLogName) + /-! Size measures for termination proofs. -/ mutual def exprSize : YulExpr → Nat @@ -80,77 +85,7 @@ private theorem internal_call_measure_decreases (fuel measure : Nat) : rw [Prod.lex_iff] exact Or.inl (Nat.lt_succ_self fuel) -/-! ## Execution State for IR -/ - -structure IRState where - /-- Variable bindings (name → value) -/ - vars : List (String × Nat) - /-- Storage slots (slot → value). - - Typed via `IRStorageWord` so Phase 1 of the IR storage refactor can - flip the carrier to a `UInt256`-bounded representation without - touching this signature. Currently `IRStorageWord` is an `abbrev` - for `Nat`, so this is definitionally `Nat → Nat` and existing - callsites continue to typecheck. -/ - storage : IRStorageSlot → IRStorageWord - /-- Transient storage slots (slot → value). -/ - transientStorage : Nat → Nat := fun _ => 0 - /-- Memory words (offset → value) -/ - memory : Nat → Nat - /-- Calldata words (argument index → value) -/ - calldata : List Nat - /-- Return value (if any) -/ - returnValue : Option Nat - /-- Sender address -/ - sender : Nat - /-- Msg.value seen by `callvalue()`. -/ - msgValue : Nat := 0 - /-- Contract address seen by `address()`. -/ - thisAddress : Nat := 0 - /-- Block timestamp seen by `timestamp()`. -/ - blockTimestamp : Nat := 0 - /-- Block number seen by `number()`. -/ - blockNumber : Nat := 0 - /-- Chain id seen by `chainid()`. -/ - chainId : Nat := 0 - /-- Blob base fee seen by `blobbasefee()`. -/ - blobBaseFee : Nat := 0 - /-- Function selector (4-byte value used by calldataload(0)) -/ - selector : Nat - /-- Emitted log records for this execution. -/ - events : List (List Nat) := [] - deriving Nonempty - -/-- Initial state for IR execution -/ -def IRState.initial (sender : Nat) : IRState := - { vars := [] - storage := fun _ => 0 - transientStorage := fun _ => 0 - memory := fun _ => 0 - calldata := [] - returnValue := none - sender := sender - msgValue := 0 - thisAddress := 0 - blockTimestamp := 0 - blockNumber := 0 - chainId := 0 - blobBaseFee := 0 - selector := 0 - events := [] } - -/-- Lookup variable in state -/ -def IRState.getVar (s : IRState) (name : String) : Option Nat := - s.vars.find? (·.1 == name) |>.map (·.2) - -/-- Set variable in state -/ -def IRState.setVar (s : IRState) (name : String) (value : Nat) : IRState := - { s with vars := (name, value) :: s.vars.filter (·.1 != name) } - -/-- Set several variables in order, matching the left-to-right binding behavior used -by parameter initialization and multi-return helper calls. -/ -def IRState.setVars (s : IRState) (bindings : List (String × Nat)) : IRState := - bindings.foldl (fun st (name, value) => st.setVar name value) s +/-! ## Execution State Helpers -/ def byteWordCount (size : Nat) : Nat := (size + 31) / 32 @@ -184,10 +119,6 @@ def IRState.appendYulLog (s : IRState) (offset size : Nat) (topics : List Nat) : IRState := { s with events := s.events ++ [encodeYulLogEvent s.memory offset size topics] } -def isYulLogName (func : String) : Bool := - func == "log0" || func == "log1" || func == "log2" || - func == "log3" || func == "log4" - def applyYulLogCall? (state : IRState) (func : String) (argVals : List Nat) : Option IRState := match func, argVals with @@ -334,8 +265,7 @@ def evalIRCall (state : IRState) (func : String) : List YulExpr → Option Nat | [offset, size] => some (abstractKeccakMemorySlice state.memory offset size) | _ => none else - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext - Compiler.Proofs.YulGeneration.defaultBuiltinBackend + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext state.storage state.sender state.msgValue state.thisAddress state.blockTimestamp state.blockNumber state.chainId state.blobBaseFee state.selector state.calldata func argVals termination_by args => exprsSize args + 1 @@ -385,8 +315,21 @@ end -- mutual (fun offset => some (Compiler.Proofs.YulGeneration.calldataloadWord state.selector state.calldata offset)) := by simp [evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean] + cases evalIRExpr state argExpr with + | none => simp + | some val => simp + +@[simp] theorem evalIRCall_sload_singleton + (state : IRState) (argExpr : YulExpr) : + evalIRCall state "sload" [argExpr] = + (evalIRExpr state argExpr).bind + (fun slot => some (Compiler.Proofs.abstractLoadStorageOrMapping state.storage slot).toNat) := by + simp [evalIRCall, evalIRExprs, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, + Compiler.Proofs.abstractLoadStorageOrMapping] cases evalIRExpr state argExpr with | none => simp | some val => simp @@ -535,8 +478,7 @@ def evalIRCallWithInternals | [offset, size] => .values [abstractKeccakMemorySlice state'.memory offset size] state' | _ => .revert state' else - match Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext - Compiler.Proofs.YulGeneration.defaultBuiltinBackend + match Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext state'.storage state'.sender state'.msgValue state'.thisAddress state'.blockTimestamp state'.blockNumber state'.chainId state'.blobBaseFee state'.selector state'.calldata func argVals with @@ -1079,6 +1021,11 @@ theorem execIRStmts_sstore_lit_expr_then_stop_succ_succ_succ_of_eval .stop state := by simp only [execIRStmts, execIRStmt] +@[simp] theorem execIRStmts_single_leave_succ_succ (fuel : Nat) (state : IRState) : + execIRStmts (Nat.succ (Nat.succ fuel)) state [YulStmt.leave] = + .continue state := by + simp only [execIRStmts, execIRStmt] + /-- A top-level `length + 1` fuel budget is not sufficient once a single list is wrapped in a `block`: entering the block consumes one step and leaves only `1` fuel for the nested body, which immediately reverts on its first @@ -1096,18 +1043,6 @@ theorem execIRStmts_single_block_stop_length_insufficient /-! ## IR Function Execution -/ -structure IRTransaction where - sender : Nat - msgValue : Nat := 0 - thisAddress : Nat := 0 - blockTimestamp : Nat := 0 - blockNumber : Nat := 0 - chainId : Nat := 0 - blobBaseFee : Nat := 0 - functionSelector : Nat - args : List Nat - deriving Repr - /-- Apply transaction context fields to an IR state, leaving storage and other non-transaction fields unchanged. -/ @[reducible] def IRState.withTx (s : IRState) (tx : IRTransaction) : IRState := @@ -1129,13 +1064,6 @@ other non-transaction fields unchanged. -/ @[simp] theorem IRState.withTx_events (s : IRState) (tx : IRTransaction) : (s.withTx tx).events = s.events := rfl -structure IRResult where - success : Bool - returnValue : Option Nat - finalStorage : IRStorageSlot → IRStorageWord - finalMappings : Nat → Nat → IRStorageWord - events : List (List Nat) - /-- Execute an IR function with given arguments. Uses `sizeOf fn.body + 1` fuel, which is sufficient for any terminating execution of a non-looping function body. -/ @@ -1226,13 +1154,20 @@ noncomputable def interpretIR (contract : IRContract) (tx : IRTransaction) (init chainId := tx.chainId blobBaseFee := tx.blobBaseFee calldata := tx.args + returnValue := none selector := tx.functionSelector } -- Find matching function by selector match contract.functions.find? (·.selector == tx.functionSelector) with | some fn => - if _ : fn.params.length ≤ tx.args.length then + if !fn.payable && tx.msgValue % Compiler.Constants.evmModulus != 0 then + { success := false + returnValue := none + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } + else if _ : fn.params.length ≤ tx.args.length then execIRFunction fn tx.args initialState else { success := false @@ -1264,11 +1199,18 @@ noncomputable def interpretIRWithInternals chainId := tx.chainId blobBaseFee := tx.blobBaseFee calldata := tx.args + returnValue := none selector := tx.functionSelector } match contract.functions.find? (·.selector == tx.functionSelector) with | some fn => - if _ : fn.params.length ≤ tx.args.length then + if !fn.payable && tx.msgValue % Compiler.Constants.evmModulus != 0 then + { success := false + returnValue := none + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } + else if _ : fn.params.length ≤ tx.args.length then execIRFunctionWithInternals contract helperFuel fn tx.args initialState else { success := false @@ -1419,8 +1361,7 @@ theorem evalIRExprWithInternals_eq_evalIRExpr_of_no_internal cases rest <;> simp · simp only [htload, hmload, hkeccak, ↓reduceIte] cases hbuiltin : - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext - Compiler.Proofs.YulGeneration.defaultBuiltinBackend + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext state.storage state.sender state.msgValue state.thisAddress state.blockTimestamp state.blockNumber state.chainId state.blobBaseFee state.selector state.calldata func argVals with | none => simp [hbuiltin] @@ -1583,8 +1524,7 @@ theorem evalIRExprWithInternals_eq_evalIRExpr_of_callsDisjoint cases rest <;> simp · simp only [htload, hmload, hkeccak, ↓reduceIte] cases hbuiltin : - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext - Compiler.Proofs.YulGeneration.defaultBuiltinBackend + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext state.storage state.sender state.msgValue state.thisAddress state.blockTimestamp state.blockNumber state.chainId state.blobBaseFee state.selector state.calldata func argVals with | none => simp [hbuiltin] @@ -1752,8 +1692,7 @@ theorem evalIRCallWithInternals_stmt_eq_of_callsDisjoint cases rest <;> simp · simp only [htload, hmload, hkeccak, ↓reduceIte] cases hbuiltin : - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext - Compiler.Proofs.YulGeneration.defaultBuiltinBackend + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext state.storage state.sender state.msgValue state.thisAddress state.blockTimestamp state.blockNumber state.chainId state.blobBaseFee state.selector state.calldata func argVals with | none => simp [hbuiltin] @@ -1805,8 +1744,7 @@ theorem evalIRCallWithInternals_stmt_eq_of_no_internal cases rest <;> simp · simp only [htload, hmload, hkeccak, ↓reduceIte] cases hbuiltin : - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext - Compiler.Proofs.YulGeneration.defaultBuiltinBackend + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext state.storage state.sender state.msgValue state.thisAddress state.blockTimestamp state.blockNumber state.chainId state.blobBaseFee state.selector state.calldata func argVals with | none => simp [hbuiltin] @@ -3258,8 +3196,81 @@ def applyIRTransactionContext (tx : IRTransaction) (initialState : IRState) : IR chainId := tx.chainId blobBaseFee := tx.blobBaseFee calldata := tx.args + returnValue := none selector := tx.functionSelector } +theorem interpretIR_eq_execIRFunction_of_find?_some_guards + (contract : IRContract) + (tx : IRTransaction) + (initialState : IRState) + (fn : IRFunction) + (hFind : + contract.functions.find? (·.selector == tx.functionSelector) = some fn) + (hValue : + fn.payable = false → + tx.msgValue % Compiler.Constants.evmModulus = 0) + (hArgs : fn.params.length ≤ tx.args.length) : + interpretIR contract tx initialState = + execIRFunction fn tx.args (applyIRTransactionContext tx initialState) := by + unfold interpretIR applyIRTransactionContext + rw [hFind] + by_cases hPayable : fn.payable + · simp [hPayable, hArgs] + · have hPayableFalse : fn.payable = false := Bool.eq_false_iff.2 hPayable + have hMsgValue : tx.msgValue % Compiler.Constants.evmModulus = 0 := + hValue hPayableFalse + simp [hPayableFalse, hMsgValue, hArgs] + +theorem interpretIR_eq_revert_of_find?_some_nonpayable_nonzero + (contract : IRContract) + (tx : IRTransaction) + (initialState : IRState) + (fn : IRFunction) + (hFind : + contract.functions.find? (·.selector == tx.functionSelector) = some fn) + (hNonPayable : fn.payable = false) + (hNonzero : tx.msgValue % Compiler.Constants.evmModulus ≠ 0) : + interpretIR contract tx initialState = + { success := false + returnValue := none + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + unfold interpretIR + rw [hFind] + simp [hNonPayable, hNonzero] + +theorem interpretIR_eq_revert_of_find?_some_args_short + (contract : IRContract) + (tx : IRTransaction) + (initialState : IRState) + (fn : IRFunction) + (hFind : + contract.functions.find? (·.selector == tx.functionSelector) = some fn) + (hValue : + fn.payable = true ∨ + tx.msgValue % Compiler.Constants.evmModulus = 0) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + interpretIR contract tx initialState = + { success := false + returnValue := none + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + unfold interpretIR + rw [hFind] + by_cases hPayableTrue : fn.payable = true + · simp [hPayableTrue, hArgsShort] + · have hPayableFalse : fn.payable = false := by + cases hp : fn.payable + · rfl + · exact False.elim (hPayableTrue hp) + have hMsgValue : tx.msgValue % Compiler.Constants.evmModulus = 0 := by + rcases hValue with hValue | hValue + · simp [hPayableFalse] at hValue + · exact hValue + simp [hPayableFalse, hMsgValue, hArgsShort] + /-- Dispatch-local restatement of the helper-free runtime-contract boundary. This is equivalent to `LegacyCompatibleRuntimeContract`, but packages the remaining compiled-side retarget goal around the actually selected external @@ -3334,8 +3345,10 @@ theorem interpretIRWithInternalsZeroConservativeExtensionGoal_of_dispatchGoal tx initialState fn hfind simp only [interpretIRWithInternals, interpretIR, hfind] split - · exact hdispatchCompat · rfl + · split + · exact hdispatchCompat + · rfl /-- After the preceding reductions, the first compiled-side helper retarget theorem is equivalent to proving the stmt-list compatibility field alone. The @@ -3553,8 +3566,10 @@ theorem interpretIRWithInternalsZeroConservativeExtensionGoalOfDisjoint_closed contract fn tx.args stateWithTx hbody simp only [interpretIRWithInternals, interpretIR, hfind] split - · exact hfnEq · rfl + · split + · exact hfnEq + · rfl /-- The legacy `_closed` goal is a corollary of the disjoint version: any contract satisfying `LegacyCompatibleRuntimeContract` also satisfies @@ -3602,8 +3617,7 @@ theorem evalIRCallWithInternals_of_builtin (hnotMload : func ≠ "mload") (hnotKeccak : func ≠ "keccak256") : evalIRCallWithInternals contract fuel state func args = - match Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext - Compiler.Proofs.YulGeneration.defaultBuiltinBackend + match Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext state'.storage state'.sender state'.msgValue state'.thisAddress state'.blockTimestamp state'.blockNumber state'.chainId state'.blobBaseFee state'.selector state'.calldata func argVals with @@ -3878,6 +3892,293 @@ private theorem setVars_field_preservation {f : IRState → α} (s.setVars bindings).events = s.events := setVars_field_preservation (fun _ _ _ => rfl) s bindings +private theorem foldl_setParamVars_field_preservation {f : IRState → α} + (hsetVar : ∀ s name value, f (s.setVar name value) = f s) + (s : IRState) (bindings : List (IRParam × Nat)) : + f (bindings.foldl (fun st entry => st.setVar entry.1.name entry.2) s) = + f s := by + induction bindings generalizing s with + | nil => rfl + | cons hd tl ih => + simpa [List.foldl, hsetVar] using ih (s.setVar hd.1.name hd.2) + +@[simp] theorem IRState.foldl_setParamVars_storage + (s : IRState) (bindings : List (IRParam × Nat)) : + (bindings.foldl (fun st entry => st.setVar entry.1.name entry.2) s).storage = + s.storage := + foldl_setParamVars_field_preservation (fun _ _ _ => rfl) s bindings + +@[simp] theorem IRState.foldl_setParamVars_calldata + (s : IRState) (bindings : List (IRParam × Nat)) : + (bindings.foldl (fun st entry => st.setVar entry.1.name entry.2) s).calldata = + s.calldata := + foldl_setParamVars_field_preservation (fun _ _ _ => rfl) s bindings + +@[simp] theorem IRState.foldl_setParamVars_returnValue + (s : IRState) (bindings : List (IRParam × Nat)) : + (bindings.foldl (fun st entry => st.setVar entry.1.name entry.2) s).returnValue = + s.returnValue := + foldl_setParamVars_field_preservation (fun _ _ _ => rfl) s bindings + +@[simp] theorem IRState.foldl_setParamVars_events + (s : IRState) (bindings : List (IRParam × Nat)) : + (bindings.foldl (fun st entry => st.setVar entry.1.name entry.2) s).events = + s.events := + foldl_setParamVars_field_preservation (fun _ _ _ => rfl) s bindings + +@[simp] theorem execIRFunction_empty_body + (fn : IRFunction) (args : List Nat) (initialState : IRState) + (hBody : fn.body = []) : + execIRFunction fn args initialState = + { success := true + returnValue := initialState.returnValue + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + rw [execIRFunction] + simp [hBody, execIRStmts.eq_1] + +@[simp] theorem execIRFunction_single_stop + (fn : IRFunction) (args : List Nat) (initialState : IRState) + (hBody : fn.body = [YulStmt.expr (YulExpr.call "stop" [])]) : + execIRFunction fn args initialState = + { success := true + returnValue := none + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + rw [execIRFunction] + simp [hBody] + +theorem execIRFunction_store0_calldataload4_stop_of_args_cons + (fn : IRFunction) (tx : IRTransaction) (initialState : IRState) + (arg : Nat) (rest : List Nat) + (hBody : fn.body = [ + YulStmt.let_ "value" (YulExpr.call "calldataload" [YulExpr.lit 4]), + YulStmt.expr (YulExpr.call "sstore" [YulExpr.lit 0, YulExpr.ident "value"]), + YulStmt.expr (YulExpr.call "stop" [])]) + (hArgs : tx.args = arg :: rest) : + execIRFunction fn tx.args (applyIRTransactionContext tx initialState) = + { success := true + returnValue := none + finalStorage := + Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 + (arg % Compiler.Constants.evmModulus) + finalMappings := + Compiler.Proofs.storageAsMappings + (Compiler.Proofs.abstractStoreStorageOrMapping initialState.storage 0 + (arg % Compiler.Constants.evmModulus)) + events := initialState.events } := by + have hbody : ∀ (n : Nat) (s : IRState), 3 ≤ n → + execIRStmts (n + 1) s + [YulStmt.let_ "value" (YulExpr.call "calldataload" [YulExpr.lit 4]), + YulStmt.expr (YulExpr.call "sstore" + [YulExpr.lit 0, YulExpr.ident "value"]), + YulStmt.expr (YulExpr.call "stop" [])] = + .stop + { s.setVar "value" (Compiler.Proofs.YulGeneration.calldataloadWord + s.selector s.calldata 4) with + storage := Compiler.Proofs.abstractStoreStorageOrMapping + s.storage 0 (Compiler.Proofs.YulGeneration.calldataloadWord + s.selector s.calldata 4) } := by + intro n s hn + obtain ⟨k, rfl⟩ : ∃ k, n = k + 3 := ⟨n - 3, by omega⟩ + simp +decide [execIRStmts, execIRStmt, evalIRExpr, IRState.getVar, + IRState.setVar] + have hsize : 3 ≤ sizeOf + ([YulStmt.let_ "value" (YulExpr.call "calldataload" [YulExpr.lit 4]), + YulStmt.expr (YulExpr.call "sstore" + [YulExpr.lit 0, YulExpr.ident "value"]), + YulStmt.expr (YulExpr.call "stop" [])] : List YulStmt) := by + decide + unfold execIRFunction + simp only [hBody, hArgs] + rw [hbody _ _ hsize] + simp only [IRState.setVar_events, IRState.foldl_setParamVars_storage, + IRState.foldl_setParamVars_calldata, IRState.foldl_setParamVars_events] + simp [Compiler.Proofs.abstractStoreStorageOrMapping_eq, + Compiler.Proofs.YulGeneration.calldataloadWord, Compiler.Constants.evmModulus, + applyIRTransactionContext, hArgs] + +theorem execIRFunction_mstore0_calldataload4_return32_of_args_cons + (fn : IRFunction) (tx : IRTransaction) (initialState : IRState) + (arg : Nat) (rest : List Nat) + (hBody : fn.body = [ + YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, YulExpr.call "calldataload" [YulExpr.lit 4]]), + YulStmt.expr (YulExpr.call "return" [YulExpr.lit 0, YulExpr.lit 32])]) + (hArgs : tx.args = arg :: rest) : + execIRFunction fn tx.args (applyIRTransactionContext tx initialState) = + { success := true + returnValue := some (arg % Compiler.Constants.evmModulus) + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + have hbody : ∀ (n : Nat) (s : IRState), 2 ≤ n → + execIRStmts (n + 1) s + [YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, YulExpr.call "calldataload" [YulExpr.lit 4]]), + YulStmt.expr (YulExpr.call "return" + [YulExpr.lit 0, YulExpr.lit 32])] = + .return (Compiler.Proofs.YulGeneration.calldataloadWord + s.selector s.calldata 4) + { s with memory := fun o => + if o = 0 then (Compiler.Proofs.YulGeneration.calldataloadWord + s.selector s.calldata 4) + else s.memory o } := by + intro n s hn + obtain ⟨k, rfl⟩ : ∃ k, n = k + 2 := ⟨n - 2, by omega⟩ + simp +decide only [execIRStmts, execIRStmt, evalIRExpr, + evalIRCall_calldataload_singleton, Option.bind_some, ↓reduceIte] + have hsize : 2 ≤ sizeOf + ([YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, YulExpr.call "calldataload" [YulExpr.lit 4]]), + YulStmt.expr (YulExpr.call "return" + [YulExpr.lit 0, YulExpr.lit 32])] : List YulStmt) := by + decide + unfold execIRFunction + simp only [hBody, hArgs] + rw [hbody _ _ hsize] + simp only [IRState.foldl_setParamVars_storage, + IRState.foldl_setParamVars_calldata, IRState.foldl_setParamVars_events] + simp [Compiler.Proofs.YulGeneration.calldataloadWord, Compiler.Constants.evmModulus, + applyIRTransactionContext, hArgs] + +private theorem yulStmtList_length_le_sizeOf : (stmts : List YulStmt) → stmts.length ≤ sizeOf stmts + | [] => by simp + | _ :: rest => by + have hrest := yulStmtList_length_le_sizeOf rest + simp + omega + +theorem execIRFunction_mstore0_calldataload_aligned_return32 + (fn : IRFunction) (tx : IRTransaction) (initialState : IRState) + (idx : Nat) + (hBody : fn.body = [ + YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, + YulExpr.call "calldataload" [YulExpr.lit (4 + 32 * idx)]]), + YulStmt.expr (YulExpr.call "return" [YulExpr.lit 0, YulExpr.lit 32])]) : + execIRFunction fn tx.args (applyIRTransactionContext tx initialState) = + { success := true + returnValue := some (tx.args.getD idx 0 % Compiler.Constants.evmModulus) + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + have hbody : ∀ (n : Nat) (s : IRState), 2 ≤ n → + execIRStmts (n + 1) s + [YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, + YulExpr.call "calldataload" [YulExpr.lit (4 + 32 * idx)]]), + YulStmt.expr (YulExpr.call "return" + [YulExpr.lit 0, YulExpr.lit 32])] = + .return (Compiler.Proofs.YulGeneration.calldataloadWord + s.selector s.calldata (4 + 32 * idx)) + { s with memory := fun o => + if o = 0 then (Compiler.Proofs.YulGeneration.calldataloadWord + s.selector s.calldata (4 + 32 * idx)) + else s.memory o } := by + intro n s hn + obtain ⟨k, rfl⟩ : ∃ k, n = k + 2 := ⟨n - 2, by omega⟩ + simp +decide only [execIRStmts, execIRStmt, evalIRExpr, + evalIRCall_calldataload_singleton, Option.bind_some, ↓reduceIte] + have hsize : 2 ≤ sizeOf + ([YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, + YulExpr.call "calldataload" [YulExpr.lit (4 + 32 * idx)]]), + YulStmt.expr (YulExpr.call "return" + [YulExpr.lit 0, YulExpr.lit 32])] : List YulStmt) := by + have hlen := yulStmtList_length_le_sizeOf + ([YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, + YulExpr.call "calldataload" [YulExpr.lit (4 + 32 * idx)]]), + YulStmt.expr (YulExpr.call "return" + [YulExpr.lit 0, YulExpr.lit 32])] : List YulStmt) + simpa using hlen + unfold execIRFunction + simp only [hBody] + rw [hbody _ _ hsize] + simp only [IRState.foldl_setParamVars_storage, + IRState.foldl_setParamVars_calldata, IRState.foldl_setParamVars_events] + simp [Compiler.Proofs.YulGeneration.calldataloadWord, Compiler.Constants.evmModulus, + applyIRTransactionContext] + +theorem execIRFunction_mstore0_sload0_return32 + (fn : IRFunction) (tx : IRTransaction) (initialState : IRState) + (hBody : fn.body = [ + YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, YulExpr.call "sload" [YulExpr.lit 0]]), + YulStmt.expr (YulExpr.call "return" [YulExpr.lit 0, YulExpr.lit 32])]) : + execIRFunction fn tx.args (applyIRTransactionContext tx initialState) = + { success := true + returnValue := some ((initialState.storage (IRStorageSlot.ofNat 0)).toNat) + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + have hbody : ∀ (n : Nat) (s : IRState), 2 ≤ n → + execIRStmts (n + 1) s + [YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, YulExpr.call "sload" [YulExpr.lit 0]]), + YulStmt.expr (YulExpr.call "return" + [YulExpr.lit 0, YulExpr.lit 32])] = + .return ((s.storage (IRStorageSlot.ofNat 0)).toNat) + { s with memory := fun o => + if o = 0 then (s.storage (IRStorageSlot.ofNat 0)).toNat else s.memory o } := by + intro n s hn + obtain ⟨k, rfl⟩ : ∃ k, n = k + 2 := ⟨n - 2, by omega⟩ + simp +decide only [execIRStmts, execIRStmt, evalIRExpr, evalIRCall_sload_singleton, + Compiler.Proofs.abstractLoadStorageOrMapping, + Option.bind_some, ↓reduceIte] + have hsize : 2 ≤ sizeOf + ([YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, YulExpr.call "sload" [YulExpr.lit 0]]), + YulStmt.expr (YulExpr.call "return" + [YulExpr.lit 0, YulExpr.lit 32])] : List YulStmt) := by + decide + unfold execIRFunction + simp only [hBody] + rw [hbody _ _ hsize] + simp only [IRState.foldl_setParamVars_storage, + IRState.foldl_setParamVars_events] + simp [applyIRTransactionContext] + +theorem execIRFunction_mstore0_lit_return32 + (fn : IRFunction) (tx : IRTransaction) (initialState : IRState) + (value : Nat) + (hBody : fn.body = [ + YulStmt.expr (YulExpr.call "mstore" [YulExpr.lit 0, YulExpr.lit value]), + YulStmt.expr (YulExpr.call "return" [YulExpr.lit 0, YulExpr.lit 32])]) : + execIRFunction fn tx.args (applyIRTransactionContext tx initialState) = + { success := true + returnValue := some value + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } := by + have hbody : ∀ (n : Nat) (s : IRState), 2 ≤ n → + execIRStmts (n + 1) s + [YulStmt.expr (YulExpr.call "mstore" [YulExpr.lit 0, YulExpr.lit value]), + YulStmt.expr (YulExpr.call "return" + [YulExpr.lit 0, YulExpr.lit 32])] = + .return value { s with memory := fun o => if o = 0 then value else s.memory o } := by + intro n s hn + obtain ⟨k, rfl⟩ : ∃ k, n = k + 2 := ⟨n - 2, by omega⟩ + simp +decide only [execIRStmts, execIRStmt, evalIRExpr, ↓reduceIte] + have hsize : 2 ≤ sizeOf + ([YulStmt.expr (YulExpr.call "mstore" [YulExpr.lit 0, YulExpr.lit value]), + YulStmt.expr (YulExpr.call "return" + [YulExpr.lit 0, YulExpr.lit 32])] : List YulStmt) := by + have hlen := yulStmtList_length_le_sizeOf + ([YulStmt.expr (YulExpr.call "mstore" [YulExpr.lit 0, YulExpr.lit value]), + YulStmt.expr (YulExpr.call "return" + [YulExpr.lit 0, YulExpr.lit 32])] : List YulStmt) + simpa using hlen + unfold execIRFunction + simp only [hBody] + rw [hbody _ _ hsize] + simp only [IRState.foldl_setParamVars_storage, + IRState.foldl_setParamVars_events] + simp [applyIRTransactionContext] + /-- `prepareInternalCalleeState` preserves storage from the caller. -/ @[simp] theorem prepareInternalCalleeState_storage (callerState : IRState) (helper : IRInternalFunctionDef) (args : List Nat) : @@ -4411,6 +4712,21 @@ theorem execIRStmtsWithInternals_of_internalCall_compile (applyIRTransactionContext tx initialState).calldata = tx.args := by simp only [applyIRTransactionContext] +@[simp] theorem applyIRTransactionContext_storage + (tx : IRTransaction) (initialState : IRState) : + (applyIRTransactionContext tx initialState).storage = initialState.storage := by + simp only [applyIRTransactionContext] + +@[simp] theorem applyIRTransactionContext_returnValue + (tx : IRTransaction) (initialState : IRState) : + (applyIRTransactionContext tx initialState).returnValue = none := by + simp only [applyIRTransactionContext] + +@[simp] theorem applyIRTransactionContext_events + (tx : IRTransaction) (initialState : IRState) : + (applyIRTransactionContext tx initialState).events = initialState.events := by + simp only [applyIRTransactionContext] + private def shortCalldataRegressionContract : IRContract := { name := "ShortCalldataRegression" deploy := [] diff --git a/Compiler/Proofs/IRGeneration/IRRuntimeTypes.lean b/Compiler/Proofs/IRGeneration/IRRuntimeTypes.lean new file mode 100644 index 000000000..f8cad54c7 --- /dev/null +++ b/Compiler/Proofs/IRGeneration/IRRuntimeTypes.lean @@ -0,0 +1,93 @@ +import Compiler.Proofs.IRGeneration.IRStorageWord + +namespace Compiler.Proofs.IRGeneration + +/-- Proof-side execution state shared by IR semantics and native-runtime harnesses. -/ +structure IRState where + /-- Variable bindings (name -> value). -/ + vars : List (String × Nat) + /-- Storage slots (slot -> value). + + Typed via `IRStorageWord` so the proof surface tracks the bounded EVM + storage carrier. -/ + storage : IRStorageSlot → IRStorageWord + /-- Transient storage slots (slot -> value). -/ + transientStorage : Nat → Nat := fun _ => 0 + /-- Memory words (offset -> value). -/ + memory : Nat → Nat + /-- Calldata words. -/ + calldata : List Nat + /-- Return value, if any. -/ + returnValue : Option Nat + /-- Sender address. -/ + sender : Nat + /-- Msg.value seen by `callvalue()`. -/ + msgValue : Nat := 0 + /-- Contract address seen by `address()`. -/ + thisAddress : Nat := 0 + /-- Block timestamp seen by `timestamp()`. -/ + blockTimestamp : Nat := 0 + /-- Block number seen by `number()`. -/ + blockNumber : Nat := 0 + /-- Chain id seen by `chainid()`. -/ + chainId : Nat := 0 + /-- Blob base fee seen by `blobbasefee()`. -/ + blobBaseFee : Nat := 0 + /-- Function selector. -/ + selector : Nat + /-- Emitted log records for this execution. -/ + events : List (List Nat) := [] + deriving Nonempty + +/-- Initial state for IR execution. -/ +def IRState.initial (sender : Nat) : IRState := + { vars := [] + storage := fun _ => 0 + transientStorage := fun _ => 0 + memory := fun _ => 0 + calldata := [] + returnValue := none + sender := sender + msgValue := 0 + thisAddress := 0 + blockTimestamp := 0 + blockNumber := 0 + chainId := 0 + blobBaseFee := 0 + selector := 0 + events := [] } + +/-- Lookup variable in state. -/ +def IRState.getVar (s : IRState) (name : String) : Option Nat := + s.vars.find? (·.1 == name) |>.map (·.2) + +/-- Set variable in state. -/ +def IRState.setVar (s : IRState) (name : String) (value : Nat) : IRState := + { s with vars := (name, value) :: s.vars.filter (·.1 != name) } + +/-- Set several variables in order, matching left-to-right binding behavior. -/ +def IRState.setVars (s : IRState) (bindings : List (String × Nat)) : IRState := + bindings.foldl (fun st (name, value) => st.setVar name value) s + +/-- Proof-side transaction context shared by IR and native-runtime harnesses. -/ +structure IRTransaction where + sender : Nat + msgValue : Nat := 0 + thisAddress : Nat := 0 + blockTimestamp : Nat := 0 + blockNumber : Nat := 0 + chainId : Nat := 0 + blobBaseFee : Nat := 0 + functionSelector : Nat + args : List Nat + deriving Repr + +/-- Proof-side observable execution result shared by IR and native-runtime harnesses. -/ +structure IRResult where + success : Bool + returnValue : Option Nat + finalStorage : IRStorageSlot → IRStorageWord + finalMappings : Nat → Nat → IRStorageWord + events : List (List Nat) + +end Compiler.Proofs.IRGeneration diff --git a/Compiler/Proofs/IRGeneration/ParamLoading.lean b/Compiler/Proofs/IRGeneration/ParamLoading.lean index 3b2f78b0d..8c766466d 100644 --- a/Compiler/Proofs/IRGeneration/ParamLoading.lean +++ b/Compiler/Proofs/IRGeneration/ParamLoading.lean @@ -116,8 +116,8 @@ theorem exec_genScalarLoad_supported Verity.Core.UINT256_MODULUS, uint256_modulus_eq_evm] using hdecode.symm cases hvalue simp [genScalarLoad, execIRStmts, execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, calldataloadWord_aligned] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, calldataloadWord_aligned] case uint8 => simp [SourceSemantics.decodeSupportedParamWord, SourceSemantics.wordNormalize, SourceSemantics.uint8Modulus] at hdecode @@ -125,8 +125,8 @@ theorem exec_genScalarLoad_supported have h255 : (255 : Nat) % Compiler.Constants.evmModulus = 255 := by norm_num [Compiler.Constants.evmModulus] simp [genScalarLoad, execIRStmts, execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, calldataloadWord_aligned, h255] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, calldataloadWord_aligned, h255] case address => simp [SourceSemantics.decodeSupportedParamWord, SourceSemantics.wordNormalize] at hdecode subst value @@ -137,15 +137,15 @@ theorem exec_genScalarLoad_supported omega exact Nat.mod_eq_of_lt hlt simp [genScalarLoad, execIRStmts, execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, calldataloadWord_aligned, hmask] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, calldataloadWord_aligned, hmask] case bool => simp only [SourceSemantics.decodeSupportedParamWord, SourceSemantics.wordNormalize, Option.some.injEq] at hdecode subst value simp [genScalarLoad, execIRStmts, execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, calldataloadWord_aligned] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, calldataloadWord_aligned] split <;> simp_all private theorem getD_eq_of_drop_eq_cons @@ -206,8 +206,8 @@ private theorem exec_genScalarLoad_supported_then_word_passthrough Verity.Core.UINT256_MODULUS, uint256_modulus_eq_evm] using hdecode.symm cases hvalue simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, calldataloadWord_aligned] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, calldataloadWord_aligned] simpa [genScalarLoad, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using execIRStmts_cons_of_execIRStmt_continue_extraFuel extraFuel state (state.setVar name value) (YulStmt.let_ name (YulExpr.call "calldataload" [YulExpr.lit (4 + 32 * idx)])) rest hstmt @@ -232,8 +232,8 @@ private theorem exec_genScalarLoad_supported_then_uint8 have h255 : (255 : Nat) % Compiler.Constants.evmModulus = 255 := by norm_num [Compiler.Constants.evmModulus] simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, calldataloadWord_aligned, h255] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, calldataloadWord_aligned, h255] simpa [genScalarLoad, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using execIRStmts_cons_of_execIRStmt_continue_extraFuel extraFuel state (state.setVar name value) (YulStmt.let_ name @@ -262,8 +262,8 @@ private theorem exec_genScalarLoad_supported_then_address omega exact Nat.mod_eq_of_lt hlt simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, calldataloadWord_aligned, hmask] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, calldataloadWord_aligned, hmask] simpa [genScalarLoad, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using execIRStmts_cons_of_execIRStmt_continue_extraFuel extraFuel state (state.setVar name value) (YulStmt.let_ name @@ -288,8 +288,8 @@ private theorem exec_genScalarLoad_supported_then_bool Option.some.injEq] at hdecode subst value simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, calldataloadWord_aligned] + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, calldataloadWord_aligned] split <;> simp_all simpa [genScalarLoad, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using execIRStmts_cons_of_execIRStmt_continue_extraFuel extraFuel state (state.setVar name value) @@ -363,8 +363,8 @@ private theorem exec_minInputSizeCheck_supported_noop have hnotlt : ¬ 4 + state.calldata.length * 32 < 4 + 32 * params.length := by omega simp [execIRStmt, evalIRExpr, evalIRCall, evalIRExprs, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext, - Compiler.Proofs.YulGeneration.evalBuiltinCallWithContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext, + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean, Nat.mod_eq_of_lt hcalldataSizeFits, Nat.mod_eq_of_lt hrhs_lt_modulus, hnotlt] theorem exec_genParamLoadBodyFrom_supported_then diff --git a/Compiler/Proofs/IRGeneration/SourceSemantics.lean b/Compiler/Proofs/IRGeneration/SourceSemantics.lean index dced869a6..a4243ef34 100644 --- a/Compiler/Proofs/IRGeneration/SourceSemantics.lean +++ b/Compiler/Proofs/IRGeneration/SourceSemantics.lean @@ -2388,7 +2388,11 @@ def interpretConstructor (spec : CompilationModel) (ctor : ConstructorSpec) def interpretContract (spec : CompilationModel) (selectors : List Nat) (tx : IRTransaction) (initialWorld : Verity.ContractState) : SourceContractResult := match findFunctionBySelector spec selectors tx.functionSelector with - | some fn => interpretFunction spec fn tx initialWorld + | some fn => + if !fn.isPayable && tx.msgValue % Compiler.Constants.evmModulus != 0 then + revertedResult spec (withTransactionContext initialWorld tx) + else + interpretFunction spec fn tx initialWorld | none => revertedResult spec (withTransactionContext initialWorld tx) -- The ceilDiv case pushes the equation-compiler's `simp` past 200 000 heartbeats. @@ -3153,7 +3157,11 @@ def interpretContractWithHelpers (tx : IRTransaction) (initialWorld : Verity.ContractState) : SourceContractResult := match findFunctionBySelector spec selectors tx.functionSelector with - | some fn => interpretFunctionWithHelpers spec fuel fn tx initialWorld + | some fn => + if !fn.isPayable && tx.msgValue % Compiler.Constants.evmModulus != 0 then + revertedResult spec (withTransactionContext initialWorld tx) + else + interpretFunctionWithHelpers spec fuel fn tx initialWorld | none => revertedResult spec (withTransactionContext initialWorld tx) theorem helperSummarySound @@ -4303,13 +4311,15 @@ theorem interpretContractWithHelpers_eq_interpretContract_of_supportedSpec have hfn : fn ∈ selectorDispatchedFunctions spec := findFunctionBySelector_mem_selectorDispatchedFunctions hfind have hfnModel : fn ∈ spec.functions := List.mem_of_mem_filter hfn - exact interpretFunctionWithHelpers_eq_interpretFunction_of_helperSurfaceClosed - (spec := spec) - (fuel := fuel) - (fn := fn) - (tx := tx) - (initialWorld := initialWorld) - (hSupported.supportedFunctionOfSelectorDispatched hfn).body.helperSurfaceClosed + split + · rfl + · exact interpretFunctionWithHelpers_eq_interpretFunction_of_helperSurfaceClosed + (spec := spec) + (fuel := fuel) + (fn := fn) + (tx := tx) + (initialWorld := initialWorld) + (hSupported.supportedFunctionOfSelectorDispatched hfn).body.helperSurfaceClosed · rfl theorem interpretContractWithHelpers_eq_interpretContract_of_supportedSpecExceptMappingWrites @@ -4326,13 +4336,15 @@ theorem interpretContractWithHelpers_eq_interpretContract_of_supportedSpecExcept · rename_i fn hfind have hfn : fn ∈ selectorDispatchedFunctions spec := findFunctionBySelector_mem_selectorDispatchedFunctions hfind - exact interpretFunctionWithHelpers_eq_interpretFunction_of_helperSurfaceClosed - (spec := spec) - (fuel := fuel) - (fn := fn) - (tx := tx) - (initialWorld := initialWorld) - (hSupported.supportedFunctionOfSelectorDispatched hfn).body.helperSurfaceClosed + split + · rfl + · exact interpretFunctionWithHelpers_eq_interpretFunction_of_helperSurfaceClosed + (spec := spec) + (fuel := fuel) + (fn := fn) + (tx := tx) + (initialWorld := initialWorld) + (hSupported.supportedFunctionOfSelectorDispatched hfn).body.helperSurfaceClosed · rfl end SourceSemantics diff --git a/Compiler/Proofs/IRGeneration/SupportedSpec.lean b/Compiler/Proofs/IRGeneration/SupportedSpec.lean index 1d2007917..920833fdf 100644 --- a/Compiler/Proofs/IRGeneration/SupportedSpec.lean +++ b/Compiler/Proofs/IRGeneration/SupportedSpec.lean @@ -666,6 +666,7 @@ current whole-contract theorem. -/ structure SupportedParamProfile (params : List Param) : Prop where namesNodup : (params.map (·.name)).Nodup supported : ∀ param ∈ params, SupportedExternalParamType param.ty + calldataThreshold : 4 + params.length * 32 < Compiler.Constants.evmModulus /-- Return-profile interface for selector-dispatched entrypoints covered by the current whole-contract theorem. -/ @@ -2240,6 +2241,12 @@ theorem SupportedFunction.paramsSupported ∀ param ∈ fn.params, SupportedExternalParamType param.ty := hSupported.params.supported +theorem SupportedFunction.paramCalldataThreshold + {spec : CompilationModel} {fn : FunctionSpec} + (hSupported : SupportedFunction spec fn) : + 4 + fn.params.length * 32 < Compiler.Constants.evmModulus := + hSupported.params.calldataThreshold + theorem SupportedFunction.returnsSupported {spec : CompilationModel} {fn : FunctionSpec} (hSupported : SupportedFunction spec fn) : @@ -2260,6 +2267,12 @@ theorem SupportedFunctionExceptMappingWrites.paramsSupported ∀ param ∈ fn.params, SupportedExternalParamType param.ty := hSupported.params.supported +theorem SupportedFunctionExceptMappingWrites.paramCalldataThreshold + {spec : CompilationModel} {fn : FunctionSpec} + (hSupported : SupportedFunctionExceptMappingWrites spec fn) : + 4 + fn.params.length * 32 < Compiler.Constants.evmModulus := + hSupported.params.calldataThreshold + theorem SupportedFunctionExceptMappingWrites.returnsSupported {spec : CompilationModel} {fn : FunctionSpec} (hSupported : SupportedFunctionExceptMappingWrites spec fn) : @@ -5467,6 +5480,14 @@ theorem SupportedSpec.selectorFunctionParamsSupported ∀ param ∈ fn.params, SupportedExternalParamType param.ty := (hSupported.supportedFunctionOfSelectorDispatched hfn).params.supported +theorem SupportedSpec.selectorFunctionParamCalldataThreshold + {spec : CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpec spec selectors) + {fn : FunctionSpec} + (hfn : fn ∈ selectorDispatchedFunctions spec) : + 4 + fn.params.length * 32 < Compiler.Constants.evmModulus := + (hSupported.supportedFunctionOfSelectorDispatched hfn).params.calldataThreshold + theorem SupportedSpecExceptMappingWrites.selectorFunctionParamsSupported {spec : CompilationModel} {selectors : List Nat} (hSupported : SupportedSpecExceptMappingWrites spec selectors) @@ -5475,6 +5496,14 @@ theorem SupportedSpecExceptMappingWrites.selectorFunctionParamsSupported ∀ param ∈ fn.params, SupportedExternalParamType param.ty := (hSupported.supportedFunctionOfSelectorDispatched hfn).params.supported +theorem SupportedSpecExceptMappingWrites.selectorFunctionParamCalldataThreshold + {spec : CompilationModel} {selectors : List Nat} + (hSupported : SupportedSpecExceptMappingWrites spec selectors) + {fn : FunctionSpec} + (hfn : fn ∈ selectorDispatchedFunctions spec) : + 4 + fn.params.length * 32 < Compiler.Constants.evmModulus := + (hSupported.supportedFunctionOfSelectorDispatched hfn).params.calldataThreshold + theorem SupportedSpec.selectorFunctionParamNamesNodup {spec : CompilationModel} {selectors : List Nat} (hSupported : SupportedSpec spec selectors) @@ -5550,7 +5579,8 @@ private def counter_supported_function : nonSpecialEntrypoint := rfl params := { namesNodup := by decide - supported := by intro param hparam; cases hparam } + supported := by intro param hparam; cases hparam + calldataThreshold := by decide } returns := { resolved := ⟨[.uint256], rfl, trivial⟩ } body := { stmtList := .terminalCore (.return_ (.literal 42) (by simp [FunctionBody.exprBoundNamesInScope, FunctionBody.exprBoundNames]) .nil) @@ -5633,7 +5663,8 @@ private def simpleStorage_supported_function : nonSpecialEntrypoint := rfl params := { namesNodup := by decide - supported := by intro param hparam; cases hparam } + supported := by intro param hparam; cases hparam + calldataThreshold := by decide } returns := { resolved := ⟨[.uint256], rfl, trivial⟩ } body := { stmtList := .terminalCore (.return_ (.literal 11) (by simp [FunctionBody.exprBoundNamesInScope, FunctionBody.exprBoundNames]) .nil) diff --git a/Compiler/Proofs/README.md b/Compiler/Proofs/README.md index ee329cfb3..6d04528df 100644 --- a/Compiler/Proofs/README.md +++ b/Compiler/Proofs/README.md @@ -1,6 +1,7 @@ # Compiler Verification Proofs -Formal verification proofs for the Verity compiler pipeline: `EDSL -> CompilationModel -> IR -> Yul`. +Formal verification proofs for the Verity compiler pipeline: +`EDSL -> CompilationModel -> IR -> native EVMYulLean`. See [TRUST_ASSUMPTIONS.md](../../TRUST_ASSUMPTIONS.md) for the full trust boundary and [veritylang.com/verification](https://veritylang.com/verification) for proof status. @@ -8,7 +9,7 @@ See [TRUST_ASSUMPTIONS.md](../../TRUST_ASSUMPTIONS.md) for the full trust bounda - **Layer 1: EDSL = CompilationModel** -- Frontend semantic bridge. Generic typed-IR core in [`TypedIRCompilerCorrectness.lean`](../../Compiler/TypedIRCompilerCorrectness.lean); contract-level bridges are per-contract. - **Layer 2: CompilationModel -> IR** -- Generic whole-contract theorem in [`Contract.lean`](IRGeneration/Contract.lean). 0 sorry, 0 axioms. -- **Layer 3: IR -> Yul** -- Generic statement/function equivalence in [`Preservation.lean`](YulGeneration/Preservation.lean). Dispatch bridge is an explicit theorem hypothesis. +- **Native Layer 3: IR -> native EVMYulLean** -- Runtime lowering and dispatcher execution through [`YulGeneration/Backends/EvmYulLeanNativeHarness.lean`](YulGeneration/Backends/EvmYulLeanNativeHarness.lean), composed in [`EndToEnd.lean`](EndToEnd.lean). The older custom-interpreter Yul preservation stack remains lower transition/scaffolding, not the public EndToEnd theorem target. All three layers carry zero project-specific axioms. @@ -16,14 +17,16 @@ All three layers carry zero project-specific axioms. | File | Role | |------|------| -| [`EndToEnd.lean`](EndToEnd.lean) | Composed Layers 2+3 theorem | +| [`EndToEnd.lean`](EndToEnd.lean) | Composed Layer 2 + native EVMYulLean theorem surface | | [`IRGeneration/Contract.lean`](IRGeneration/Contract.lean) | Generic whole-contract Layer 2 theorem | | [`IRGeneration/SupportedFragment.lean`](IRGeneration/SupportedFragment.lean) | `SupportedStmtList` fragment definition | | [`IRGeneration/SupportedSpec.lean`](IRGeneration/SupportedSpec.lean) | Feature-local body interfaces | | [`IRGeneration/SourceSemantics.lean`](IRGeneration/SourceSemantics.lean) | Helper-aware source semantics | | [`IRGeneration/GenericInduction.lean`](IRGeneration/GenericInduction.lean) | Helper-aware induction interfaces | -| [`YulGeneration/StatementEquivalence.lean`](YulGeneration/StatementEquivalence.lean) | All 8 Yul statement types proven | -| [`YulGeneration/Preservation.lean`](YulGeneration/Preservation.lean) | IR -> Yul codegen preservation | +| [`YulGeneration/Backends/EvmYulLeanNativeHarness.lean`](YulGeneration/Backends/EvmYulLeanNativeHarness.lean) | Native EVMYulLean runtime lowering and dispatcher-exec harness | +| [`YulGeneration/Backends/EvmYulLeanRetarget.lean`](YulGeneration/Backends/EvmYulLeanRetarget.lean) | Isolated backend-wrapper transition evidence for the bridged fragment | +| [`YulGeneration/StatementEquivalence.lean`](YulGeneration/StatementEquivalence.lean) | Legacy custom-interpreter statement equivalence scaffolding | +| [`YulGeneration/Preservation.lean`](YulGeneration/Preservation.lean) | Legacy custom-interpreter IR -> Yul preservation scaffolding | ## Layer 2 Boundary Status diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean index 908121afd..b897a4102 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean @@ -251,27 +251,39 @@ def collectYulStmtWriteNames | [] => [] | stmt :: rest => writeStmt stmt ++ collectYulStmtWriteNames writeStmt rest -partial def yulStmtWriteNames : YulStmt → List String +mutual +def yulStmtWriteNames : YulStmt → List String | .comment _ | .expr _ | .leave => [] | .let_ name _ => [name] | .letMany names _ => names | .assign name _ => [name] - | .if_ _ body => collectYulStmtWriteNames yulStmtWriteNames body + | .if_ _ body => yulStmtsWriteNames body | .for_ init _ post body => - collectYulStmtWriteNames yulStmtWriteNames init ++ - collectYulStmtWriteNames yulStmtWriteNames post ++ - collectYulStmtWriteNames yulStmtWriteNames body + yulStmtsWriteNames init ++ yulStmtsWriteNames post ++ + yulStmtsWriteNames body | .switch _ cases defaultBody => - cases.foldl - (fun acc (_, body) => - acc ++ collectYulStmtWriteNames yulStmtWriteNames body) [] ++ - collectYulStmtWriteNames yulStmtWriteNames (defaultBody.getD []) - | .block stmts => collectYulStmtWriteNames yulStmtWriteNames stmts + yulSwitchCasesWriteNames cases ++ + match defaultBody with + | none => [] + | some body => yulStmtsWriteNames body + | .block stmts => yulStmtsWriteNames stmts | .funcDef _ params rets body => - params ++ rets ++ collectYulStmtWriteNames yulStmtWriteNames body + params ++ rets ++ yulStmtsWriteNames body +termination_by stmt => sizeOf stmt +decreasing_by all_goals simp_wf; all_goals omega + +def yulStmtsWriteNames : List YulStmt → List String + | [] => [] + | stmt :: rest => yulStmtWriteNames stmt ++ yulStmtsWriteNames rest +termination_by stmts => sizeOf stmts +decreasing_by all_goals simp_wf; all_goals omega -def yulStmtsWriteNames (stmts : List YulStmt) : List String := - collectYulStmtWriteNames yulStmtWriteNames stmts +def yulSwitchCasesWriteNames : List (Nat × List YulStmt) → List String + | [] => [] + | (_, body) :: rest => yulStmtsWriteNames body ++ yulSwitchCasesWriteNames rest +termination_by cases => sizeOf cases +decreasing_by all_goals simp_wf; all_goals omega +end def collectNativeStmtWriteNames (writeStmt : EvmYul.Yul.Ast.Stmt → List String) : @@ -280,22 +292,32 @@ def collectNativeStmtWriteNames | stmt :: rest => writeStmt stmt ++ collectNativeStmtWriteNames writeStmt rest -partial def nativeStmtWriteNames : EvmYul.Yul.Ast.Stmt → List String - | .Block stmts => collectNativeStmtWriteNames nativeStmtWriteNames stmts +mutual +def nativeStmtWriteNames : EvmYul.Yul.Ast.Stmt → List String + | .Block stmts => nativeStmtsWriteNames stmts | .Let names _ => names | .ExprStmtCall _ | .Continue | .Break | .Leave => [] | .Switch _ cases defaultBody => - cases.foldl - (fun acc (_, body) => - acc ++ collectNativeStmtWriteNames nativeStmtWriteNames body) [] ++ - collectNativeStmtWriteNames nativeStmtWriteNames defaultBody - | .For _ post body => - collectNativeStmtWriteNames nativeStmtWriteNames post ++ - collectNativeStmtWriteNames nativeStmtWriteNames body - | .If _ body => collectNativeStmtWriteNames nativeStmtWriteNames body - -def nativeStmtsWriteNames (stmts : List EvmYul.Yul.Ast.Stmt) : List String := - collectNativeStmtWriteNames nativeStmtWriteNames stmts + nativeSwitchCasesWriteNames cases ++ nativeStmtsWriteNames defaultBody + | .For _ post body => nativeStmtsWriteNames post ++ nativeStmtsWriteNames body + | .If _ body => nativeStmtsWriteNames body +termination_by stmt => sizeOf stmt +decreasing_by all_goals simp_wf; all_goals omega + +def nativeStmtsWriteNames : List EvmYul.Yul.Ast.Stmt → List String + | [] => [] + | stmt :: rest => nativeStmtWriteNames stmt ++ nativeStmtsWriteNames rest +termination_by stmts => sizeOf stmts +decreasing_by all_goals simp_wf; all_goals omega + +def nativeSwitchCasesWriteNames : + List (EvmYul.Yul.Ast.Literal × List EvmYul.Yul.Ast.Stmt) → List String + | [] => [] + | (_, body) :: rest => + nativeStmtsWriteNames body ++ nativeSwitchCasesWriteNames rest +termination_by cases => sizeOf cases +decreasing_by all_goals simp_wf; all_goals omega +end def nativeSwitchDiscrTempName (switchId : Nat) : String := s!"__verity_native_switch_discr_{switchId}" @@ -365,7 +387,7 @@ def lowerNativeSwitchBlock caseIfs ++ defaultIf) /-- Native switch lowering expands to a lazy guarded block instead of using - EVMYulLean's eager `.Switch` form. The native/interpreter dispatcher proof + EVMYulLean's eager `.Switch` form. The native/EVMYulLean dispatcher proof should consume this shape directly: the first statement evaluates the discriminator once, each case is guarded by `iszero(matched) && discr == tag`, and the optional default runs only if no case marked the switch matched. -/ @@ -487,7 +509,7 @@ def lowerStmtsNative : /-- Statement-list native lowering exposes a stable head/tail equation. This is the statement-level analogue of the top-level runtime partition -equations below: future native/interpreter preservation proofs can reason by +equations below: future native/EVMYulLean preservation proofs can reason by the source statement list instead of treating the native lowerer as an opaque executable. -/ theorem lowerStmtsNativeWithSwitchIds_cons @@ -894,7 +916,7 @@ function map rather than appending it to dispatcher code. Keeping this equation named is important for the native migration proof: it is the first generated-fragment shape fact needed before proving that -`callDispatcher` runs the same selected body as the interpreter oracle. -/ +`callDispatcher` runs the same selected body as the EVMYulLean fuel wrapper. -/ theorem lowerRuntimeContractNativeAux_funcDef_cons (reservedNames : List String) (dispatcherAcc : List EvmYul.Yul.Ast.Stmt) @@ -912,6 +934,27 @@ theorem lowerRuntimeContractNativeAux_funcDef_cons lowerRuntimeContractNativeAux reservedNames rest dispatcherAcc functionsAcc nextSwitchId) := by rw [lowerRuntimeContractNativeAux.eq_2] +/-- Specialization of `lowerRuntimeContractNativeAux_funcDef_cons` for the +first helper definition in a runtime: once the helper body lowers, inserting it +into the empty native function map cannot hit the duplicate-definition guard. -/ +theorem lowerRuntimeContractNativeAux_funcDef_cons_empty_of_lowerFunctionDefinition + (reservedNames : List String) + (dispatcherAcc : List EvmYul.Yul.Ast.Stmt) + (nextSwitchId : Nat) + (name : String) + (params rets : List String) + (body rest : List YulStmt) + (definition : EvmYul.Yul.Ast.FunctionDefinition) + (hLower : lowerFunctionDefinitionNativeWithReserved + reservedNames params rets body = .ok definition) : + lowerRuntimeContractNativeAux reservedNames + (YulStmt.funcDef name params rets body :: rest) + dispatcherAcc (∅ : NativeFunctionMap) nextSwitchId = + lowerRuntimeContractNativeAux reservedNames rest dispatcherAcc + ((∅ : NativeFunctionMap).insert name definition) nextSwitchId := by + rw [lowerRuntimeContractNativeAux_funcDef_cons, hLower] + simp [insertNativeFunction, Bind.bind, Except.bind, Pure.pure, Except.pure] + /-- Top-level native runtime lowering appends non-`funcDef` statements to the dispatcher accumulator after statement lowering. @@ -1063,7 +1106,7 @@ def evalPureBuiltinViaEvmYulLean the abstract `storage : IRStorageSlot → IRStorageWord` into EVMYulLean's `Storage` recovers the same value). `mappingSlot` is bridged by routing through `abstractMappingSlot` — the same keccak-faithful Solidity mapping-slot - derivation used by Verity's `evalBuiltinCallWithContext`; both backends + derivation used by Verity's `legacyEvalBuiltinCallWithContext`; both backends ultimately compute `keccak256(abi.encode(key, baseSlot))`. Remaining context-dependent builtins (`caller`, `address`, `timestamp`, ...) are routed at the `evalBuiltinCallWithBackendContext` level. -/ diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapterCorrectness.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapterCorrectness.lean index 8ea159285..ae15eca21 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapterCorrectness.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapterCorrectness.lean @@ -12,7 +12,7 @@ 2. **For init-hoisting**: EVMYulLean's `For` has no init block; the adapter emits `init' ++ [.For cond post' body']`. This is semantically valid - because `execYulFuel` executes the init block once before entering the + because `legacyExecYulFuel` executes the init block once before entering the loop, then recurses with `for_ [] cond post body`. Both proofs establish that executing the Verity AST directly and executing @@ -33,14 +33,14 @@ open Compiler.Proofs.YulGeneration /-! ## Assign ↔ Let Semantic Equivalence Both `YulStmt.assign name value` and `YulStmt.let_ name value` execute -identically in `execYulFuel`: they evaluate `value` and call `state.setVar`. +identically in `legacyExecYulFuel`: they evaluate `value` and call `state.setVar`. This justifies the adapter's lowering of `assign` to `Let`. -/ /-- Assign and let_ produce identical execution results for all states and fuel values. This is the core semantic justification for the adapter's Assign → Let lowering. -/ -theorem assign_equiv_let (fuel : Nat) (state : YulState) +private theorem assign_equiv_let (fuel : Nat) (state : YulState) (name : String) (value : YulExpr) : execYulStmtFuel fuel state (.assign name value) = execYulStmtFuel fuel state (.let_ name value) := by @@ -49,7 +49,7 @@ theorem assign_equiv_let (fuel : Nat) (state : YulState) | succ n => rfl /-- Variant of the assign/let equivalence for the noncomputable wrapper. -/ -theorem assign_equiv_let' (state : YulState) +private theorem assign_equiv_let' (state : YulState) (name : String) (value : YulExpr) : execYulStmt state (.assign name value) = execYulStmt state (.let_ name value) := by @@ -63,17 +63,17 @@ The adapter transforms `for_ init cond post body` into identical results: executing the for loop with init is the same as executing init as a prefix, then the loop with empty init. -The key insight is that `execYulFuel` handles `for_` by: +The key insight is that `legacyExecYulFuel` handles `for_` by: 1. Executing `init` to get state `s'` 2. If init succeeds, checking `cond` on `s'` 3. Recursing with `for_ [] cond post body` -When init is empty, step 1 is a no-op: `execYulFuel fuel state (.stmts []) = .continue state`. +When init is empty, step 1 is a no-op: `legacyExecYulFuel fuel state (.stmts []) = .continue state`. So `for_ [] cond post body` starts directly at step 2. -/ /-- Executing an empty statement list is a no-op for any fuel value. -/ -@[simp] theorem execYulFuel_stmts_nil (fuel : Nat) (state : YulState) : - execYulFuel fuel state (.stmts []) = .continue state := by +@[simp] private theorem legacyExecYulFuel_stmts_nil (fuel : Nat) (state : YulState) : + legacyExecYulFuel fuel state (.stmts []) = .continue state := by cases fuel <;> rfl /-- Init-hoisting for the continue case: when init succeeds with state `s'`, @@ -81,33 +81,33 @@ So `for_ [] cond post body` starts directly at step 2. -/ This is the core semantic justification for the adapter's transformation of `for (init; cond; post) body` into `init; for (; cond; post) body`. -/ -theorem for_init_hoist (fuel : Nat) (state : YulState) +private theorem for_init_hoist (fuel : Nat) (state : YulState) (init : List YulStmt) (cond : YulExpr) (post body : List YulStmt) - (s' : YulState) (hinit : execYulFuel fuel state (.stmts init) = .continue s') : + (s' : YulState) (hinit : legacyExecYulFuel fuel state (.stmts init) = .continue s') : execYulStmtFuel (fuel + 1) state (.for_ init cond post body) = execYulStmtFuel (fuel + 1) s' (.for_ [] cond post body) := by - simp [execYulStmtFuel, execYulFuel, hinit, execYulFuel_stmts_nil] + simp [execYulStmtFuel, legacyExecYulFuel, hinit, legacyExecYulFuel_stmts_nil] /-- Init-hoisting for the revert case. -/ -theorem for_init_hoist_revert (fuel : Nat) (state : YulState) +private theorem for_init_hoist_revert (fuel : Nat) (state : YulState) (init : List YulStmt) (cond : YulExpr) (post body : List YulStmt) - (s : YulState) (hinit : execYulFuel fuel state (.stmts init) = .revert s) : + (s : YulState) (hinit : legacyExecYulFuel fuel state (.stmts init) = .revert s) : execYulStmtFuel (fuel + 1) state (.for_ init cond post body) = .revert s := by - simp [execYulStmtFuel, execYulFuel, hinit] + simp [execYulStmtFuel, legacyExecYulFuel, hinit] /-- Init-hoisting for the return case. -/ -theorem for_init_hoist_return (fuel : Nat) (state : YulState) +private theorem for_init_hoist_return (fuel : Nat) (state : YulState) (init : List YulStmt) (cond : YulExpr) (post body : List YulStmt) - (v : Nat) (s : YulState) (hinit : execYulFuel fuel state (.stmts init) = .return v s) : + (v : Nat) (s : YulState) (hinit : legacyExecYulFuel fuel state (.stmts init) = .return v s) : execYulStmtFuel (fuel + 1) state (.for_ init cond post body) = .return v s := by - simp [execYulStmtFuel, execYulFuel, hinit] + simp [execYulStmtFuel, legacyExecYulFuel, hinit] /-- Init-hoisting for the stop case. -/ -theorem for_init_hoist_stop (fuel : Nat) (state : YulState) +private theorem for_init_hoist_stop (fuel : Nat) (state : YulState) (init : List YulStmt) (cond : YulExpr) (post body : List YulStmt) - (s : YulState) (hinit : execYulFuel fuel state (.stmts init) = .stop s) : + (s : YulState) (hinit : legacyExecYulFuel fuel state (.stmts init) = .stop s) : execYulStmtFuel (fuel + 1) state (.for_ init cond post body) = .stop s := by - simp [execYulStmtFuel, execYulFuel, hinit] + simp [execYulStmtFuel, legacyExecYulFuel, hinit] /-! ## Combined: the adapter's lowering preserves semantics diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean index 220885f5f..7155aaf45 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean @@ -21,8 +21,10 @@ Run: lake build Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBodyClosure -/ -import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanRetarget +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgePredicates import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanSourceExprClosure +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanNativeHarness +import Compiler.TypedIRCompilerCorrectness import Compiler.CompilationModel.Compile import Compiler.CompilationModel.ParamLoading @@ -34,6 +36,7 @@ open Compiler open Compiler.Yul open Compiler.CompilationModel open Compiler.Proofs.YulGeneration +open Verity.Core.Free /-- Scalar ABI parameter types handled inline by `genScalarLoad`. These are the `ParamType` constructors whose head word is consumed directly from @@ -440,6 +443,201 @@ theorem genParamLoads_scalar_bridged exact BridgedStmt.straight _ bridgedStraightStmt_revert_zero · exact genParamLoadBodyFrom_calldataload_bridged _ 4 params 4 hScalar stmt hMem +private theorem genScalarLoad_noFuncDefs + (loadWord : YulExpr → YulExpr) (name : String) + (ty : ParamType) (offset : Nat) : + Native.yulStmtsContainFuncDef + (genScalarLoad loadWord name ty offset) = false := by + cases ty <;> simp [genScalarLoad, Native.yulStmtContainsFuncDef] + +private theorem genStaticTypeLoads_go_noFuncDefs + (loadWord : YulExpr → YulExpr) (name : String) + (tys : List ParamType) (idx curOffset : Nat) + (hNoFunc : + ∀ ty ∈ tys, ∀ (name : String) (offset : Nat), + Native.yulStmtsContainFuncDef + (genStaticTypeLoads loadWord name ty offset) = false) : + Native.yulStmtsContainFuncDef + (genStaticTypeLoads.go loadWord name tys idx curOffset) = false := by + induction tys generalizing idx curOffset with + | nil => + rw [genStaticTypeLoads.go.eq_def] + simp + | cons elemTy rest ih => + rw [genStaticTypeLoads.go.eq_def] + have hHere := hNoFunc elemTy (by simp) s!"{name}_{idx}" curOffset + have hTail : + ∀ ty ∈ rest, ∀ (name : String) (offset : Nat), + Native.yulStmtsContainFuncDef + (genStaticTypeLoads loadWord name ty offset) = false := by + intro ty hMem + exact hNoFunc ty (by simp [hMem]) + simp [hHere, ih (idx + 1) (curOffset + paramHeadSize elemTy) hTail] + +private theorem genStaticTypeLoads_noFuncDefs + (loadWord : YulExpr → YulExpr) (name : String) + (ty : ParamType) (offset : Nat) + (hStatic : IsStaticScalarParamType ty) : + Native.yulStmtsContainFuncDef + (genStaticTypeLoads loadWord name ty offset) = false := by + induction hStatic generalizing name offset with + | @scalar ty hScalar => + cases ty <;> simp [IsScalarParamType, genStaticTypeLoads.eq_def] at hScalar ⊢ + all_goals + exact genScalarLoad_noFuncDefs loadWord name _ offset + | @fixedArray elemTy n hElem ih => + rw [genStaticTypeLoads.eq_7] + exact Native.yulStmtsContainFuncDef_flatMap_false + (List.range n) + (fun i => + genStaticTypeLoads loadWord s!"{name}_{i}" elemTy + (offset + i * paramHeadSize elemTy)) + (by + intro i _hi + exact ih s!"{name}_{i}" (offset + i * paramHeadSize elemTy)) + | @tuple elemTys hElems hElems_ih => + rw [genStaticTypeLoads.eq_8] + exact genStaticTypeLoads_go_noFuncDefs loadWord name elemTys 0 offset + hElems_ih + +private theorem fixedArrayFirstAlias_noFuncDefs + (name : String) (elemTy : ParamType) (n : Nat) : + Native.yulStmtsContainFuncDef + (if n == 0 then [] + else + if isScalarParamType elemTy then + [YulStmt.let_ name (YulExpr.ident s!"{name}_0")] + else + []) = false := by + by_cases hN : n == 0 + · simp [hN] + · by_cases hScalar : isScalarParamType elemTy + · simp [hN, hScalar, Native.yulStmtContainsFuncDef] + · simp [hN, hScalar] + +private theorem genParamLoadBodyFrom_scalar_noFuncDefs + (loadWord : YulExpr → YulExpr) (sizeExpr : YulExpr) + (headSize baseOffset : Nat) : + ∀ (params : List Param) (headOffset : Nat), + AllScalarParams params → + Native.yulStmtsContainFuncDef + (genParamLoadBodyFrom loadWord sizeExpr headSize baseOffset + params headOffset) = false := by + intro params + induction params with + | nil => + intro headOffset _hScalar + simp [genParamLoadBodyFrom] + | cons param rest ih => + intro headOffset hScalar + rcases param with ⟨paramName, paramTy⟩ + have hHead : IsScalarParamType paramTy := + hScalar ⟨paramName, paramTy⟩ (by simp) + have hRest : AllScalarParams rest := by + intro p hp + exact hScalar p (by simp [hp]) + cases paramTy <;> simp [IsScalarParamType] at hHead + all_goals + simp [genParamLoadBodyFrom, genSingleParamLoad, genScalarLoad_noFuncDefs] + exact ih _ hRest + +/-- `genParamLoads` emits no Yul function declarations for scalar ABI +parameter lists. This is the native-fragment shape companion to +`genParamLoads_scalar_bridged`. -/ +theorem genParamLoads_scalar_noFuncDefs + (params : List Param) (hScalar : AllScalarParams params) : + Native.yulStmtsContainFuncDef (genParamLoads params) = false := by + unfold genParamLoads genParamLoadsFrom + simp [Native.yulStmtContainsFuncDef, + genParamLoadBodyFrom_scalar_noFuncDefs + (fun pos => YulExpr.call "calldataload" [pos]) + (YulExpr.call "calldatasize" []) _ 4 params 4 hScalar] + +private theorem genSingleParamLoad_static_scalar_noFuncDefs + (loadWord : YulExpr → YulExpr) (sizeExpr : YulExpr) + (headSize baseOffset : Nat) (name : String) (ty : ParamType) + (headOffset : Nat) (hStatic : IsStaticScalarParamType ty) : + Native.yulStmtsContainFuncDef + (genSingleParamLoad loadWord sizeExpr headSize baseOffset name ty + headOffset) = false := by + cases hStatic with + | scalar hScalar => + cases ty <;> simp [IsScalarParamType] at hScalar + all_goals + simp [genSingleParamLoad, genScalarLoad_noFuncDefs] + | @fixedArray elemTy n hElem => + have hStaticLoads : + Native.yulStmtsContainFuncDef + (genStaticTypeLoads loadWord name (.fixedArray elemTy n) + headOffset) = false := + genStaticTypeLoads_noFuncDefs loadWord name (.fixedArray elemTy n) + headOffset (IsStaticScalarParamType.fixedArray hElem) + have hAlias := fixedArrayFirstAlias_noFuncDefs name elemTy n + by_cases hN : n == 0 + · simp [genSingleParamLoad, + isDynamicParamType_false_of_static_scalar _ + (IsStaticScalarParamType.fixedArray hElem), + hN, hStaticLoads] + · simp [genSingleParamLoad, + isDynamicParamType_false_of_static_scalar _ + (IsStaticScalarParamType.fixedArray hElem), + hN, hStaticLoads] + simpa [hN] using hAlias + | @tuple elemTys hElems => + have hStaticLoads : + Native.yulStmtsContainFuncDef + (genStaticTypeLoads loadWord name (.tuple elemTys) headOffset) = + false := + genStaticTypeLoads_noFuncDefs loadWord name (.tuple elemTys) + headOffset (IsStaticScalarParamType.tuple hElems) + simp [genSingleParamLoad, + isDynamicParamType_false_of_static_scalar _ + (IsStaticScalarParamType.tuple hElems), + hStaticLoads] + +private theorem genParamLoadBodyFrom_static_scalar_noFuncDefs + (loadWord : YulExpr → YulExpr) (sizeExpr : YulExpr) + (headSize baseOffset : Nat) : + ∀ (params : List Param) (headOffset : Nat), + AllStaticScalarParams params → + Native.yulStmtsContainFuncDef + (genParamLoadBodyFrom loadWord sizeExpr headSize baseOffset + params headOffset) = false := by + intro params + induction params with + | nil => + intro headOffset _hStatic + simp [genParamLoadBodyFrom] + | cons param rest ih => + intro headOffset hStatic + rcases param with ⟨paramName, paramTy⟩ + have hHead : IsStaticScalarParamType paramTy := + hStatic ⟨paramName, paramTy⟩ (by simp) + have hRest : AllStaticScalarParams rest := by + intro p hp + exact hStatic p (by simp [hp]) + have hTail : + Native.yulStmtsContainFuncDef + (genParamLoadBodyFrom loadWord sizeExpr headSize baseOffset + rest (headOffset + paramHeadSize paramTy)) = false := + ih _ hRest + simp [genParamLoadBodyFrom, + genSingleParamLoad_static_scalar_noFuncDefs loadWord sizeExpr headSize + baseOffset paramName paramTy headOffset hHead, + hTail] + +/-- `genParamLoads` emits no Yul function declarations for static ABI +parameter lists whose leaves are scalar words. This is the native-fragment +shape companion to `genParamLoads_static_scalar_bridged`. -/ +theorem genParamLoads_static_scalar_noFuncDefs + (params : List Param) (hStatic : AllStaticScalarParams params) : + Native.yulStmtsContainFuncDef (genParamLoads params) = false := by + unfold genParamLoads genParamLoadsFrom + simp [Native.yulStmtContainsFuncDef, + genParamLoadBodyFrom_static_scalar_noFuncDefs + (fun pos => YulExpr.call "calldataload" [pos]) + (YulExpr.call "calldatasize" []) _ 4 params 4 hStatic] + /-- `genParamLoads` produces only bridged statements when every parameter is a static ABI value whose leaves are scalar words. This is the real prologue-level closure theorem for fixed arrays and tuples of scalar ABI types. -/ @@ -536,6 +734,38 @@ theorem compileStmt_binding_leaf_bridged exact BridgedStmt.straight _ (BridgedStraightStmt.assign name valueExpr hBridged) +/-- Scalar-leaf binding statements compile to Yul lists with no nested +function declarations. -/ +theorem compileStmt_binding_leaf_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceBindingStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | letVar name value _hValue => + simp only [compileStmt, bind, Except.bind] at hOk + cases hExpr : compileExpr fields dynamicSource value with + | error err => + simp [hExpr] at hOk + | ok valueExpr => + simp [hExpr, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + | assignVar name value _hValue => + simp only [compileStmt, bind, Except.bind] at hOk + cases hExpr : compileExpr fields dynamicSource value with + | error err => + simp [hExpr] at hOk + | ok valueExpr => + simp [hExpr, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + /-- Lists made only of scalar-leaf `letVar`/`assignVar` statements compile to Yul lists satisfying `BridgedStmts`. This is the first direct body-closure theorem over `compileStmtList`. -/ @@ -583,6 +813,52 @@ theorem compileStmtList_binding_leaf_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +/-- Lists made only of scalar-leaf `letVar`/`assignVar` statements compile to +Yul lists with no nested function declarations. -/ +theorem compileStmtList_binding_leaf_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceBindingStmts stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmts + induction stmts with + | nil => + intro inScopeNames _ out hOk + simp [compileStmtList, Pure.pure, Except.pure] at hOk + subst out + rfl + | cons head tail ih => + intro inScopeNames hSource out hOk + simp only [compileStmtList, bind, Except.bind] at hOk + cases hHead : compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] head with + | error err => + simp [hHead] at hOk + | ok headOut => + simp [hHead] at hOk + cases hTail : compileStmtList fields events errors dynamicSource internalRetNames + isInternal (collectStmtNames head ++ inScopeNames) [] tail with + | error err => + simp [hTail] at hOk + | ok tailOut => + simp [hTail, Pure.pure, Except.pure] at hOk + subst out + have hHeadSource : BridgedSourceBindingStmt head := + hSource head (by simp) + have hTailSource : BridgedSourceBindingStmts tail := by + intro stmt hMem + exact hSource stmt (by simp [hMem]) + simp [ + compileStmt_binding_leaf_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames + hHeadSource hHead, + ih (collectStmtNames head ++ inScopeNames) hTailSource hTail] + /-- A pure-expression `letVar`/`assignVar` source statement compiles to Yul that satisfies `BridgedStmts`. -/ theorem compileStmt_pure_binding_bridged @@ -627,6 +903,38 @@ theorem compileStmt_pure_binding_bridged exact BridgedStmt.straight _ (BridgedStraightStmt.assign name valueExpr hBridged) +/-- Pure-expression binding statements compile to Yul lists with no nested +function declarations. -/ +theorem compileStmt_pure_binding_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourcePureBindingStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | letVar name value _hValue => + simp only [compileStmt, bind, Except.bind] at hOk + cases hExpr : compileExpr fields dynamicSource value with + | error err => + simp [hExpr] at hOk + | ok valueExpr => + simp [hExpr, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + | assignVar name value _hValue => + simp only [compileStmt, bind, Except.bind] at hOk + cases hExpr : compileExpr fields dynamicSource value with + | error err => + simp [hExpr] at hOk + | ok valueExpr => + simp [hExpr, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + /-- Lists made only of pure-expression `letVar`/`assignVar` statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_pure_binding_bridged @@ -673,6 +981,47 @@ theorem compileStmtList_pure_binding_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +/-- Lists made only of pure-expression `letVar`/`assignVar` statements compile +to Yul lists with no nested function declarations. -/ +theorem compileStmtList_pure_binding_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), BridgedSourcePureBindingStmts stmts → + ∀ {out : List YulStmt}, compileStmtList fields events errors dynamicSource + internalRetNames isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmts + induction stmts with + | nil => + intro inScopeNames _ out hOk + simp [compileStmtList, Pure.pure, Except.pure] at hOk + subst out + rfl + | cons head tail ih => + intro inScopeNames hSource out hOk + simp only [compileStmtList, bind, Except.bind] at hOk + cases hHead : compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] head with + | error err => + simp [hHead] at hOk + | ok headOut => + simp [hHead] at hOk + cases hTail : compileStmtList fields events errors dynamicSource internalRetNames + isInternal (collectStmtNames head ++ inScopeNames) [] tail with + | error err => + simp [hTail] at hOk + | ok tailOut => + simp [hTail, Pure.pure, Except.pure] at hOk + subst out + have hHeadSource : BridgedSourcePureBindingStmt head := hSource head (by simp) + have hTailSource : BridgedSourcePureBindingStmts tail := by + intro stmt hMem; exact hSource stmt (by simp [hMem]) + simp [ + compileStmt_pure_binding_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames + hHeadSource hHead, + ih (collectStmtNames head ++ inScopeNames) hTailSource hTail] + /-! ## Source statement body closure: pure bindings plus single-slot storage writes -/ /-- Source statements in the current storage body-closure fragment. @@ -697,6 +1046,23 @@ inductive BridgedSourceStorageStmt (fields : List Field) : Stmt → Prop def BridgedSourceStorageStmts (fields : List Field) (stmts : List Stmt) : Prop := ∀ stmt ∈ stmts, BridgedSourceStorageStmt fields stmt +/-- `SupportedFragment.setStorageSingleSlot` expression and field-layout + witnesses are enough to build the native storage source-statement bridge + witness. -/ +theorem bridgedSourceStorageStmt_setStorageSingleSlot_of_exprCompileCore + {fields : List Field} {fieldName : String} {value : Expr} {slot : Nat} + (hValue : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) + (hFind : + findFieldWithResolvedSlot fields fieldName = + some ({ name := fieldName, ty := FieldType.uint256 }, slot)) : + BridgedSourceStorageStmt fields (.setStorage fieldName value) := + BridgedSourceStorageStmt.setStorage fieldName value + { name := fieldName, ty := FieldType.uint256 } slot + (bridgedSourceExpr_of_exprCompileCore hValue) + (isMapping_false_of_findFieldWithResolvedSlot_uint256 hFind rfl) + (by simpa using hFind) + (by intro name maxFields h; cases h) + /-- An unpacked single-slot `setStorage` source statement with a pure bridged right-hand side compiles to a literal-slot `sstore`, hence satisfies `BridgedStmts`. -/ @@ -737,6 +1103,39 @@ theorem compileStmt_setStorage_singleSlot_pure_bridged exact BridgedStmt.straight _ (BridgedStraightStmt.expr_sstore_lit slot valueExpr hBridged) +/-- An unpacked single-slot `setStorage` source statement with a pure bridged +right-hand side compiles to a Yul list with no nested function declarations. -/ +theorem compileStmt_setStorage_singleSlot_pure_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) (value : Expr) (f : Field) (slot : Nat) + (_hValue : BridgedSourceExpr value) + (hNotMapping : isMapping fields field = false) + (hFind : + findFieldWithResolvedSlot fields field = + some ({ f with packedBits := none, aliasSlots := [] }, slot)) + (hNotAdt : ∀ name maxFields, f.ty ≠ FieldType.adt name maxFields) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStorage field value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt] at hOk + unfold compileSetStorage at hOk + simp [hNotMapping, hFind] at hOk + cases hty : f.ty with + | adt name maxFields => + exact False.elim (hNotAdt name maxFields hty) + | uint256 | address | dynamicArray | mappingTyped | mappingStruct | mappingStruct2 => + cases hExpr : compileExpr fields dynamicSource value with + | error err => + simp [hExpr, hty] at hOk + | ok valueExpr => + simp [hExpr, hty] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + /-- Each statement in the storage fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_storage_fragment_bridged @@ -758,6 +1157,27 @@ theorem compileStmt_storage_fragment_bridged dynamicSource internalRetNames isInternal inScopeNames field value f slot hValue hNotMapping hFind hNotAdt hOk +/-- Each statement in the storage fragment compiles to a Yul list with no nested +function declarations. -/ +theorem compileStmt_storage_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStorageStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | pureBinding hPure => + exact compileStmt_pure_binding_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hPure hOk + | setStorage field value f slot hValue hNotMapping hFind hNotAdt => + exact compileStmt_setStorage_singleSlot_pure_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field value f slot + hValue hNotMapping hFind hNotAdt hOk + /-- Lists made of pure `letVar`/`assignVar` statements and unpacked single-slot `setStorage` statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_storage_fragment_bridged @@ -805,6 +1225,70 @@ theorem compileStmtList_storage_fragment_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +private theorem compileStmtList_noFuncDefs_of_forall + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) + (internalRetNames : List String) (isInternal : Bool) (P : Stmt → Prop) + (hCompile : + ∀ (inScopeNames : List String) {stmt : Stmt} {out : List YulStmt}, + P stmt → + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + (∀ stmt ∈ stmts, P stmt) → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmts + induction stmts with + | nil => + intro inScopeNames _ out hOk + simp [compileStmtList, Pure.pure, Except.pure] at hOk + subst out + rfl + | cons head tail ih => + intro inScopeNames hSource out hOk + simp only [compileStmtList, bind, Except.bind] at hOk + cases hHead : compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] head with + | error err => + simp [hHead] at hOk + | ok headOut => + simp [hHead] at hOk + cases hTail : compileStmtList fields events errors dynamicSource internalRetNames + isInternal (collectStmtNames head ++ inScopeNames) [] tail with + | error err => + simp [hTail] at hOk + | ok tailOut => + simp [hTail, Pure.pure, Except.pure] at hOk + subst out + have hHeadSource : P head := hSource head (by simp) + have hTailSource : ∀ stmt ∈ tail, P stmt := by + intro stmt hMem + exact hSource stmt (by simp [hMem]) + simp [ + hCompile inScopeNames hHeadSource hHead, + ih (collectStmtNames head ++ inScopeNames) hTailSource hTail] + +/-- Storage-fragment statement lists compile with no nested function declarations. -/ +theorem compileStmtList_storage_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) + (internalRetNames : List String) (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStorageStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceStorageStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_storage_fragment_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: `stop` and external/internal `return` Two more simple compiler-emitted source statement shapes whose Yul output is @@ -849,6 +1333,19 @@ private theorem compileStmt_stop_bridged subst yulStmt exact BridgedStmt.straight _ BridgedStraightStmt.expr_stop +private theorem compileStmt_stop_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] .stop = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, Pure.pure, Except.pure] at hOk + cases hOk + simp [Native.yulStmtContainsFuncDef] + /-- A `Stmt.return value` source statement with a `BridgedSourceExpr` RHS and `isInternal = false` compiles to a fixed two-statement Yul list satisfying `BridgedStmts`. -/ @@ -879,12 +1376,29 @@ private theorem compileStmt_return_external_bridged (BridgedStraightStmt.expr_return (.lit 0) (.lit 32) (BridgedExpr.lit 0) (BridgedExpr.lit 32)) -/-- External (`isInternal = false`) `stop`/`return` source statements compile -to Yul lists satisfying `BridgedStmts`. -/ -theorem compileStmt_terminator_external_bridged +private theorem compileStmt_return_external_noFuncDefs (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) - (inScopeNames : List String) : + (inScopeNames : List String) {value : Expr} (_hValue : BridgedSourceExpr value) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] (.return value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hExpr : compileExpr fields dynamicSource value with + | error err => simp [hExpr] at hOk + | ok valueExpr => + simp [hExpr, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + +/-- External (`isInternal = false`) `stop`/`return` source statements compile +to Yul lists satisfying `BridgedStmts`. -/ +theorem compileStmt_terminator_external_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : ∀ {stmt : Stmt}, BridgedSourceTerminatorStmt stmt → ∀ {out : List YulStmt}, compileStmt fields events errors dynamicSource internalRetNames @@ -899,6 +1413,26 @@ theorem compileStmt_terminator_external_bridged exact compileStmt_return_external_bridged fields events errors dynamicSource internalRetNames inScopeNames hValue hOk +/-- External (`isInternal = false`) `stop`/`return` source statements compile +to Yul lists with no nested function declarations. -/ +theorem compileStmt_terminator_external_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceTerminatorStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | stop => + exact compileStmt_stop_noFuncDefs fields events errors dynamicSource + internalRetNames false inScopeNames hOk + | returnExternal value hValue => + exact compileStmt_return_external_noFuncDefs fields events errors dynamicSource + internalRetNames inScopeNames hValue hOk + /-- Lists made only of external `stop`/`return` source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_terminator_external_bridged @@ -944,6 +1478,43 @@ theorem compileStmtList_terminator_external_bridged internalRetNames inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +/-- External `stop`/`return` statement lists compile with no nested function +declarations. -/ +theorem compileStmtList_terminator_external_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceTerminatorStmts stmts → ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmts + induction stmts with + | nil => + intro inScopeNames _ out hOk + simp [compileStmtList, Pure.pure, Except.pure] at hOk; subst out; rfl + | cons head tail ih => + intro inScopeNames hSource out hOk + simp only [compileStmtList, bind, Except.bind] at hOk + cases hHead : compileStmt fields events errors dynamicSource internalRetNames + false inScopeNames [] head with + | error err => simp [hHead] at hOk + | ok headOut => + simp [hHead] at hOk + cases hTail : compileStmtList fields events errors dynamicSource internalRetNames + false (collectStmtNames head ++ inScopeNames) [] tail with + | error err => simp [hTail] at hOk + | ok tailOut => + simp [hTail, Pure.pure, Except.pure] at hOk + subst out + have hHeadSource : BridgedSourceTerminatorStmt head := hSource head (by simp) + have hTailSource : BridgedSourceTerminatorStmts tail := by + intro stmt hMem; exact hSource stmt (by simp [hMem]) + simp [ + compileStmt_terminator_external_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hHeadSource hHead, + ih (collectStmtNames head ++ inScopeNames) hTailSource hTail] + /-! ### Internal return closure Internal functions return by assigning the compiled value to the first generated @@ -993,6 +1564,28 @@ theorem compileStmt_return_internal_bridged (BridgedStraightStmt.assign retName valueExpr hBridged) · exact BridgedStmt.straight _ BridgedStraightStmt.leave +theorem compileStmt_return_internal_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) + {value : Expr} (_hValue : BridgedSourceExpr value) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] (.return value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hExpr : compileExpr fields dynamicSource value with + | error err => simp [hExpr] at hOk + | ok valueExpr => + cases internalRetNames with + | nil => + simp [hExpr] at hOk + | cons retName rest => + simp [hExpr, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + /-- Internal (`isInternal = true`) `return` source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmt_internal_return_bridged @@ -1010,6 +1603,23 @@ theorem compileStmt_internal_return_bridged exact compileStmt_return_internal_bridged fields events errors dynamicSource internalRetNames inScopeNames hValue hOk +/-- Internal (`isInternal = true`) `return` source statements compile to Yul +lists with no nested function declarations. -/ +theorem compileStmt_internal_return_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceInternalReturnStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | returnInternal value hValue => + exact compileStmt_return_internal_noFuncDefs fields events errors dynamicSource + internalRetNames inScopeNames hValue hOk + /-- Lists made only of internal `return` source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_internal_return_bridged @@ -1055,6 +1665,23 @@ theorem compileStmtList_internal_return_bridged internalRetNames inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +/-- Lists made only of internal `return` source statements compile with no +nested function declarations. -/ +theorem compileStmtList_internal_return_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceInternalReturnStmts stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames true BridgedSourceInternalReturnStmt + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_internal_return_noFuncDefs fields events errors dynamicSource + internalRetNames inScopeNames hStmt hOk) + /-! ## Source statement body closure: `require` Plain `Stmt.require cond message` compiles to a Yul `if` whose body is @@ -1100,6 +1727,26 @@ private theorem revertWithMessage_bridged (message : String) : (BridgedStraightStmt.expr_revert (YulExpr.lit 0) (YulExpr.lit (68 + ((bytesFromString message).length + 31) / 32 * 32))) +private theorem revertWithMessage_chunks_noFuncDefs + (chunks : List (List UInt8 × Nat)) : + Native.yulStmtsContainFuncDef + (chunks.map + (fun chunkAndIdx => + YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit (68 + chunkAndIdx.2 * 32), + YulExpr.hex (wordFromBytes chunkAndIdx.1)]))) = false := by + induction chunks with + | nil => rfl + | cons head tail ih => + cases head with + | mk chunk idx => + simp [Native.yulStmtContainsFuncDef, ih] + +private theorem revertWithMessage_noFuncDefs (message : String) : + Native.yulStmtsContainFuncDef (revertWithMessage message) = false := by + unfold revertWithMessage + simp [Native.yulStmtContainsFuncDef, revertWithMessage_chunks_noFuncDefs] + /-- Source `require` statements whose compiled failure condition is bridged. -/ inductive BridgedSourceRequireStmt (fields : List Field) (dynamicSource : DynamicDataSource) : Stmt → Prop @@ -1114,6 +1761,31 @@ def BridgedSourceRequireStmts (fields : List Field) (dynamicSource : DynamicDataSource) (stmts : List Stmt) : Prop := ∀ stmt ∈ stmts, BridgedSourceRequireStmt fields dynamicSource stmt +/-- A `require` over a compile-core condition has a bridged compiled failure + condition, so it belongs to the native require source-statement bridge. -/ +theorem bridgedSourceRequireStmt_of_exprCompileCore + {fields : List Field} {dynamicSource : DynamicDataSource} + {cond : Expr} {message : String} + (hCond : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore cond) : + BridgedSourceRequireStmt fields dynamicSource (.require cond message) := + BridgedSourceRequireStmt.require cond message + (compileRequireFailCond_bridgedSource fields dynamicSource + (bridgedSourceExpr_of_exprCompileCore hCond)) + +/-- Every literal guard-family clause lowers to a `require` whose condition is + in the compile-core expression grammar, hence is native-bridged. -/ +theorem bridgedSourceRequireStmt_of_guardFamilyClause + {fields : List Field} {dynamicSource : DynamicDataSource} + (clause : RequireLiteralGuardFamilyClause) : + BridgedSourceRequireStmt fields dynamicSource clause.toStmt := by + cases clause with + | mk family n m p q message => + cases family <;> simp [RequireLiteralGuardFamilyClause.toStmt] + case binary op => + cases op <;> simp [RequireLiteralGuardFamilyClause.toStmt] + all_goals exact bridgedSourceRequireStmt_of_exprCompileCore (by repeat constructor) + all_goals exact bridgedSourceRequireStmt_of_exprCompileCore (by repeat constructor) + /-- A plain `Stmt.require` whose compiled failure condition is bridged compiles to a bridged Yul `if` around `revertWithMessage`. -/ theorem compileStmt_require_bridged @@ -1143,6 +1815,29 @@ theorem compileStmt_require_bridged exact BridgedStmt.if_ failCond (revertWithMessage message) (hFailCond hFail) (revertWithMessage_bridged message) +theorem compileStmt_require_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + {cond : Expr} {message : String} + (_hFailCond : + ∀ {failCond : YulExpr}, + compileRequireFailCond fields dynamicSource cond = .ok failCond → + BridgedExpr failCond) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.require cond message) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hFail : compileRequireFailCond fields dynamicSource cond with + | error err => + simp [hFail] at hOk + | ok failCond => + simp [hFail, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, revertWithMessage_noFuncDefs] + /-- Lists made only of plain `require` statements whose compiled failure conditions are bridged compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_require_bridged @@ -1192,6 +1887,26 @@ theorem compileStmtList_require_bridged (ih (collectStmtNames (.require cond message) ++ inScopeNames) hTailSource hTail) +/-- Lists made only of plain `require` statements whose compiled failure +conditions are bridged compile with no nested function declarations. -/ +theorem compileStmtList_require_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceRequireStmts fields dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceRequireStmt fields dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + match hStmt with + | BridgedSourceRequireStmt.require cond message hFailCond => + compileStmt_require_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hFailCond hOk) + /-! ## Source statement body closure: single-slot mapping writes `Stmt.setMapping` and `Stmt.setMappingUint` both go through @@ -1242,6 +1957,19 @@ private theorem compileMappingSlotWrite_singleSlot_bridged (BridgedStraightStmt.expr_sstore_mapping (.lit slot) keyExpr valueExpr (BridgedExpr.lit slot) hKey hValue) +private theorem compileMappingSlotWrite_singleSlot_noFuncDefs + (fields : List Field) (field : String) {slot : Nat} + (keyExpr valueExpr : YulExpr) (label : String) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileMappingSlotWrite fields field keyExpr valueExpr label 0 = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp [compileMappingSlotWrite, hMapping, hSlots, Pure.pure, Except.pure] at hOk + subst hOk + simp [Native.yulStmtContainsFuncDef] + /-- A single-slot `Stmt.setMapping` source write with a pure bridged key and value compiles to `BridgedStmts`. -/ theorem compileStmt_setMapping_singleSlot_bridged @@ -1301,6 +2029,54 @@ theorem compileStmt_setMappingUint_singleSlot_bridged (compileExpr_bridgedSource fields dynamicSource hValue hValueExpr) hMapping hSlots hOk +theorem compileStmt_setMapping_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key value : Expr} + (_hKey : BridgedSourceExpr key) (_hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMapping field key value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr] at hOk + exact compileMappingSlotWrite_singleSlot_noFuncDefs fields field + keyExpr valueExpr "setMapping" hMapping hSlots hOk + +theorem compileStmt_setMappingUint_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key value : Expr} + (_hKey : BridgedSourceExpr key) (_hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMappingUint field key value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr] at hOk + exact compileMappingSlotWrite_singleSlot_noFuncDefs fields field + keyExpr valueExpr "setMappingUint" hMapping hSlots hOk + /-- Each statement in the mapping-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mappingWrite_bridged @@ -1323,6 +2099,26 @@ theorem compileStmt_mappingWrite_bridged dynamicSource internalRetNames isInternal inScopeNames field hKey hValue hMapping hSlots hOk +theorem compileStmt_mappingWrite_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingWriteStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMapping field hKey hValue hMapping hSlots => + exact compileStmt_setMapping_singleSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field + hKey hValue hMapping hSlots hOk + | setMappingUint field hKey hValue hMapping hSlots => + exact compileStmt_setMappingUint_singleSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field + hKey hValue hMapping hSlots hOk + /-- Lists of single-slot mapping-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingWrite_bridged @@ -1369,6 +2165,22 @@ theorem compileStmtList_mappingWrite_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mappingWrite_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingWriteStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMappingWriteStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingWrite_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: mixed function-body fragments The fragment-specific list theorems above are useful proof bricks, but real @@ -1435,6 +2247,29 @@ theorem compileStmt_external_body_fragment_bridged exact compileStmt_terminator_external_bridged fields events errors dynamicSource internalRetNames inScopeNames hTerminator hOk +theorem compileStmt_external_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceExternalBodyStmt fields dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | storage hStorage => + exact compileStmt_storage_fragment_noFuncDefs fields events errors dynamicSource + internalRetNames false inScopeNames hStorage hOk + | require hRequire => + cases hRequire with + | require cond message hFailCond => + exact compileStmt_require_noFuncDefs fields events errors dynamicSource + internalRetNames false inScopeNames hFailCond hOk + | terminator hTerminator => + exact compileStmt_terminator_external_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hTerminator hOk + /-- Mixed external source bodies made from the currently supported fragments compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_external_body_fragment_bridged @@ -1482,6 +2317,21 @@ theorem compileStmtList_external_body_fragment_bridged dynamicSource internalRetNames inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_external_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceExternalBodyStmts fields dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames false (BridgedSourceExternalBodyStmt fields dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_external_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hStmt hOk) + /-- Each mixed internal-body statement in the currently supported fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_internal_body_fragment_bridged @@ -1510,6 +2360,32 @@ theorem compileStmt_internal_body_fragment_bridged exact compileStmt_stop_bridged fields events errors dynamicSource internalRetNames true inScopeNames hOk +theorem compileStmt_internal_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceInternalBodyStmt fields dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | storage hStorage => + exact compileStmt_storage_fragment_noFuncDefs fields events errors dynamicSource + internalRetNames true inScopeNames hStorage hOk + | require hRequire => + cases hRequire with + | require cond message hFailCond => + exact compileStmt_require_noFuncDefs fields events errors dynamicSource + internalRetNames true inScopeNames hFailCond hOk + | returnInternal hReturn => + exact compileStmt_internal_return_noFuncDefs fields events errors dynamicSource + internalRetNames inScopeNames hReturn hOk + | stop => + exact compileStmt_stop_noFuncDefs fields events errors dynamicSource + internalRetNames true inScopeNames hOk + /-- Mixed internal source bodies made from the currently supported fragments compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_internal_body_fragment_bridged @@ -1557,13 +2433,28 @@ theorem compileStmtList_internal_body_fragment_bridged dynamicSource internalRetNames inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) -/-! ## Source statement body closure: one-layer `ite` composition - -The mixed body-fragment predicates above cover straight-line source bodies. Real -entrypoints often wrap those bodies in `Stmt.ite`. The next increment covers one -compiler-emitted `if` layer whose branches are already mixed external/internal -body fragments. --/ +theorem compileStmtList_internal_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceInternalBodyStmts fields dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames true (BridgedSourceInternalBodyStmt fields dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_internal_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hStmt hOk) + +/-! ## Source statement body closure: one-layer `ite` composition + +The mixed body-fragment predicates above cover straight-line source bodies. Real +entrypoints often wrap those bodies in `Stmt.ite`. The next increment covers one +compiler-emitted `if` layer whose branches are already mixed external/internal +body fragments. +-/ /-- External source-body statements extended with one `Stmt.ite` layer whose condition is a bridged source expression and whose branches are mixed external @@ -1732,6 +2623,92 @@ theorem compileStmt_ite_internal_body_fragment_bridged (bridgedExpr_iszero_ident _) hElseBridged · cases hNil +theorem compileStmt_ite_external_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) + {cond : Expr} {thenBranch elseBranch : List Stmt} + (_hCond : BridgedSourceExpr cond) + (hThen : BridgedSourceExternalBodyStmts fields dynamicSource thenBranch) + (hElse : BridgedSourceExternalBodyStmts fields dynamicSource elseBranch) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] (.ite cond thenBranch elseBranch) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hCondExpr : compileExpr fields dynamicSource cond with + | error err => simp [hCondExpr] at hOk + | ok condExpr => + cases hThenCompile : compileStmtList fields events errors dynamicSource + internalRetNames false inScopeNames [] thenBranch with + | error err => simp [hCondExpr, hThenCompile] at hOk + | ok thenOut => + cases hElseCompile : compileStmtList fields events errors dynamicSource + internalRetNames false inScopeNames [] elseBranch with + | error err => simp [hCondExpr, hThenCompile, hElseCompile] at hOk + | ok elseOut => + have hThenNoFunc := + compileStmtList_external_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames thenBranch inScopeNames hThen + hThenCompile + have hElseNoFunc := + compileStmtList_external_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames elseBranch inScopeNames hElse + hElseCompile + by_cases hEmpty : elseBranch.isEmpty + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, Pure.pure, + Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc] + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, Pure.pure, + Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc, hElseNoFunc] + +theorem compileStmt_ite_internal_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) + {cond : Expr} {thenBranch elseBranch : List Stmt} + (_hCond : BridgedSourceExpr cond) + (hThen : BridgedSourceInternalBodyStmts fields dynamicSource thenBranch) + (hElse : BridgedSourceInternalBodyStmts fields dynamicSource elseBranch) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] (.ite cond thenBranch elseBranch) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hCondExpr : compileExpr fields dynamicSource cond with + | error err => simp [hCondExpr] at hOk + | ok condExpr => + cases hThenCompile : compileStmtList fields events errors dynamicSource + internalRetNames true inScopeNames [] thenBranch with + | error err => simp [hCondExpr, hThenCompile] at hOk + | ok thenOut => + cases hElseCompile : compileStmtList fields events errors dynamicSource + internalRetNames true inScopeNames [] elseBranch with + | error err => simp [hCondExpr, hThenCompile, hElseCompile] at hOk + | ok elseOut => + have hThenNoFunc := + compileStmtList_internal_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames thenBranch inScopeNames hThen + hThenCompile + have hElseNoFunc := + compileStmtList_internal_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames elseBranch inScopeNames hElse + hElseCompile + by_cases hEmpty : elseBranch.isEmpty + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, Pure.pure, + Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc] + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, Pure.pure, + Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc, hElseNoFunc] + /-- Each external structured-body statement in the currently supported fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_external_structured_body_fragment_bridged @@ -1752,6 +2729,24 @@ theorem compileStmt_external_structured_body_fragment_bridged exact compileStmt_ite_external_body_fragment_bridged fields events errors dynamicSource internalRetNames inScopeNames hCond hThen hElse hOk +theorem compileStmt_external_structured_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceExternalStructuredBodyStmt fields dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | base hBase => + exact compileStmt_external_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hBase hOk + | ite cond thenBranch elseBranch hCond hThen hElse => + exact compileStmt_ite_external_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hCond hThen hElse hOk + /-- External structured source bodies made from mixed body fragments plus one `Stmt.ite` layer compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_external_structured_body_fragment_bridged @@ -1799,6 +2794,22 @@ theorem compileStmtList_external_structured_body_fragment_bridged errors dynamicSource internalRetNames inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_external_structured_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceExternalStructuredBodyStmts fields dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames false + (BridgedSourceExternalStructuredBodyStmt fields dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_external_structured_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames inScopeNames hStmt hOk) + /-- Each internal structured-body statement in the currently supported fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_internal_structured_body_fragment_bridged @@ -1819,6 +2830,24 @@ theorem compileStmt_internal_structured_body_fragment_bridged exact compileStmt_ite_internal_body_fragment_bridged fields events errors dynamicSource internalRetNames inScopeNames hCond hThen hElse hOk +theorem compileStmt_internal_structured_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceInternalStructuredBodyStmt fields dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | base hBase => + exact compileStmt_internal_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hBase hOk + | ite cond thenBranch elseBranch hCond hThen hElse => + exact compileStmt_ite_internal_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hCond hThen hElse hOk + /-- Internal structured source bodies made from mixed body fragments plus one `Stmt.ite` layer compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_internal_structured_body_fragment_bridged @@ -1866,6 +2895,22 @@ theorem compileStmtList_internal_structured_body_fragment_bridged errors dynamicSource internalRetNames inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_internal_structured_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceInternalStructuredBodyStmts fields dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames true + (BridgedSourceInternalStructuredBodyStmt fields dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_internal_structured_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames inScopeNames hStmt hOk) + /-! ## Source statement body closure: nested `ite` composition The one-layer predicates above are useful for shallow source bodies. This @@ -2039,6 +3084,92 @@ theorem compileStmt_ite_internal_nested_body_fragment_bridged (bridgedExpr_iszero_ident _) hElseBridged · cases hNil +theorem compileStmt_ite_external_nested_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) + {cond : Expr} {thenBranch elseBranch : List Stmt} + (_hCond : BridgedSourceExpr cond) + (hThen : BridgedSourceExternalStructuredBodyStmts fields dynamicSource thenBranch) + (hElse : BridgedSourceExternalStructuredBodyStmts fields dynamicSource elseBranch) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] (.ite cond thenBranch elseBranch) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hCondExpr : compileExpr fields dynamicSource cond with + | error err => simp [hCondExpr] at hOk + | ok condExpr => + cases hThenCompile : compileStmtList fields events errors dynamicSource + internalRetNames false inScopeNames [] thenBranch with + | error err => simp [hCondExpr, hThenCompile] at hOk + | ok thenOut => + cases hElseCompile : compileStmtList fields events errors dynamicSource + internalRetNames false inScopeNames [] elseBranch with + | error err => simp [hCondExpr, hThenCompile, hElseCompile] at hOk + | ok elseOut => + have hThenNoFunc := + compileStmtList_external_structured_body_fragment_noFuncDefs fields + events errors dynamicSource internalRetNames thenBranch + inScopeNames hThen hThenCompile + have hElseNoFunc := + compileStmtList_external_structured_body_fragment_noFuncDefs fields + events errors dynamicSource internalRetNames elseBranch + inScopeNames hElse hElseCompile + by_cases hEmpty : elseBranch.isEmpty + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, Pure.pure, + Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc] + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, Pure.pure, + Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc, hElseNoFunc] + +theorem compileStmt_ite_internal_nested_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) + {cond : Expr} {thenBranch elseBranch : List Stmt} + (_hCond : BridgedSourceExpr cond) + (hThen : BridgedSourceInternalStructuredBodyStmts fields dynamicSource thenBranch) + (hElse : BridgedSourceInternalStructuredBodyStmts fields dynamicSource elseBranch) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] (.ite cond thenBranch elseBranch) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hCondExpr : compileExpr fields dynamicSource cond with + | error err => simp [hCondExpr] at hOk + | ok condExpr => + cases hThenCompile : compileStmtList fields events errors dynamicSource + internalRetNames true inScopeNames [] thenBranch with + | error err => simp [hCondExpr, hThenCompile] at hOk + | ok thenOut => + cases hElseCompile : compileStmtList fields events errors dynamicSource + internalRetNames true inScopeNames [] elseBranch with + | error err => simp [hCondExpr, hThenCompile, hElseCompile] at hOk + | ok elseOut => + have hThenNoFunc := + compileStmtList_internal_structured_body_fragment_noFuncDefs fields + events errors dynamicSource internalRetNames thenBranch + inScopeNames hThen hThenCompile + have hElseNoFunc := + compileStmtList_internal_structured_body_fragment_noFuncDefs fields + events errors dynamicSource internalRetNames elseBranch + inScopeNames hElse hElseCompile + by_cases hEmpty : elseBranch.isEmpty + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, Pure.pure, + Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc] + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, Pure.pure, + Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc, hElseNoFunc] + theorem compileStmt_external_nested_body_fragment_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) @@ -2057,6 +3188,24 @@ theorem compileStmt_external_nested_body_fragment_bridged exact compileStmt_ite_external_nested_body_fragment_bridged fields events errors dynamicSource internalRetNames inScopeNames hCond hThen hElse hOk +theorem compileStmt_external_nested_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceExternalNestedBodyStmt fields dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | structured hStructured => + exact compileStmt_external_structured_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames inScopeNames hStructured hOk + | ite cond thenBranch elseBranch hCond hThen hElse => + exact compileStmt_ite_external_nested_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames inScopeNames hCond hThen hElse hOk + theorem compileStmtList_external_nested_body_fragment_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) : @@ -2103,6 +3252,22 @@ theorem compileStmtList_external_nested_body_fragment_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_external_nested_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceExternalNestedBodyStmts fields dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames false + (BridgedSourceExternalNestedBodyStmt fields dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_external_nested_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hStmt hOk) + theorem compileStmt_internal_nested_body_fragment_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) @@ -2121,6 +3286,24 @@ theorem compileStmt_internal_nested_body_fragment_bridged exact compileStmt_ite_internal_nested_body_fragment_bridged fields events errors dynamicSource internalRetNames inScopeNames hCond hThen hElse hOk +theorem compileStmt_internal_nested_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceInternalNestedBodyStmt fields dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | structured hStructured => + exact compileStmt_internal_structured_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames inScopeNames hStructured hOk + | ite cond thenBranch elseBranch hCond hThen hElse => + exact compileStmt_ite_internal_nested_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames inScopeNames hCond hThen hElse hOk + theorem compileStmtList_internal_nested_body_fragment_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) : @@ -2167,6 +3350,22 @@ theorem compileStmtList_internal_nested_body_fragment_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_internal_nested_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceInternalNestedBodyStmts fields dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames true + (BridgedSourceInternalNestedBodyStmt fields dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_internal_nested_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hStmt hOk) + /-! ## Source statement body closure: recursive `ite` composition The fixed-depth predicates above are useful proof milestones, but generated @@ -2335,80 +3534,163 @@ mutual end mutual - theorem compileStmt_internal_recursive_body_fragment_bridged + theorem compileStmt_external_recursive_body_fragment_noFuncDefs (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) (inScopeNames : List String) : ∀ {stmt : Stmt}, - BridgedSourceInternalRecursiveBodyStmt fields dynamicSource stmt → + BridgedSourceExternalRecursiveBodyStmt fields dynamicSource stmt → ∀ {out : List YulStmt}, compileStmt fields events errors dynamicSource internalRetNames - (isInternal := true) inScopeNames [] stmt = .ok out → - BridgedStmts out := by + (isInternal := false) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by intro stmt hStmt out hOk cases hStmt with | base hBase => - exact compileStmt_internal_body_fragment_bridged fields events errors + exact compileStmt_external_body_fragment_noFuncDefs fields events errors dynamicSource internalRetNames inScopeNames hBase hOk - | ite cond thenBranch elseBranch hCond hThen hElse => + | ite cond thenBranch elseBranch _ hThen hElse => simp only [compileStmt, bind, Except.bind] at hOk cases hCondExpr : compileExpr fields dynamicSource cond with - | error err => - simp [hCondExpr] at hOk + | error err => simp [hCondExpr] at hOk | ok condExpr => cases hThenCompile : compileStmtList fields events errors dynamicSource - internalRetNames true inScopeNames [] thenBranch with - | error err => - simp [hCondExpr, hThenCompile] at hOk + internalRetNames false inScopeNames [] thenBranch with + | error err => simp [hCondExpr, hThenCompile] at hOk | ok thenOut => cases hElseCompile : compileStmtList fields events errors dynamicSource - internalRetNames true inScopeNames [] elseBranch with - | error err => - simp [hCondExpr, hThenCompile, hElseCompile] at hOk + internalRetNames false inScopeNames [] elseBranch with + | error err => simp [hCondExpr, hThenCompile, hElseCompile] at hOk | ok elseOut => - have hCondBridged : BridgedExpr condExpr := - compileExpr_bridgedSource fields dynamicSource hCond hCondExpr - have hThenBridged : BridgedStmts thenOut := - compileStmtList_internal_recursive_body_fragment_bridged fields - events errors dynamicSource internalRetNames hThen - inScopeNames hThenCompile - have hElseBridged : BridgedStmts elseOut := - compileStmtList_internal_recursive_body_fragment_bridged fields - events errors dynamicSource internalRetNames hElse - inScopeNames hElseCompile + have hThenNoFunc := + compileStmtList_external_recursive_body_fragment_noFuncDefs fields + events errors dynamicSource internalRetNames hThen inScopeNames + hThenCompile + have hElseNoFunc := + compileStmtList_external_recursive_body_fragment_noFuncDefs fields + events errors dynamicSource internalRetNames hElse inScopeNames + hElseCompile by_cases hEmpty : elseBranch.isEmpty · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, Pure.pure, Except.pure] at hOk subst out - intro yulStmt hMem - simp only [List.mem_singleton] at hMem - subst yulStmt - exact BridgedStmt.if_ condExpr thenOut hCondBridged hThenBridged + simp [Native.yulStmtContainsFuncDef, hThenNoFunc] · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, Pure.pure, Except.pure] at hOk subst out - intro yulStmt hMem - simp only [List.mem_singleton] at hMem - subst yulStmt - refine BridgedStmt.block _ ?_ - intro blockStmt hBlockMem - simp only [List.mem_cons, List.mem_nil_iff] at hBlockMem - rcases hBlockMem with rfl | rfl | rfl | hNil - · exact BridgedStmt.straight _ - (BridgedStraightStmt.let_ _ condExpr hCondBridged) - · exact BridgedStmt.if_ _ thenOut (BridgedExpr.ident _) hThenBridged - · exact BridgedStmt.if_ _ elseOut - (bridgedExpr_iszero_ident _) hElseBridged - · cases hNil + simp [Native.yulStmtContainsFuncDef, hThenNoFunc, hElseNoFunc] - theorem compileStmtList_internal_recursive_body_fragment_bridged + theorem compileStmtList_external_recursive_body_fragment_noFuncDefs (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) : ∀ {stmts : List Stmt}, - BridgedSourceInternalRecursiveBodyStmts fields dynamicSource stmts → + BridgedSourceExternalRecursiveBodyStmts fields dynamicSource stmts → ∀ (inScopeNames : List String) {out : List YulStmt}, compileStmtList fields events errors dynamicSource internalRetNames - (isInternal := true) inScopeNames [] stmts = .ok out → + (isInternal := false) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmts hSource inScopeNames out hOk + cases hSource with + | nil => + simp [compileStmtList, Pure.pure, Except.pure] at hOk + subst out + rfl + | @cons head tail hHead hTail => + simp only [compileStmtList, bind, Except.bind] at hOk + cases hHeadCompile : compileStmt fields events errors dynamicSource + internalRetNames false inScopeNames [] head with + | error err => simp [hHeadCompile] at hOk + | ok headOut => + simp [hHeadCompile] at hOk + cases hTailCompile : compileStmtList fields events errors dynamicSource + internalRetNames false (collectStmtNames head ++ inScopeNames) [] tail with + | error err => simp [hTailCompile] at hOk + | ok tailOut => + simp [hTailCompile, Pure.pure, Except.pure] at hOk + subst out + simp [ + compileStmt_external_recursive_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames inScopeNames hHead hHeadCompile, + compileStmtList_external_recursive_body_fragment_noFuncDefs fields + events errors dynamicSource internalRetNames hTail + (collectStmtNames head ++ inScopeNames) hTailCompile] +end + +mutual + theorem compileStmt_internal_recursive_body_fragment_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceInternalRecursiveBodyStmt fields dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmt = .ok out → + BridgedStmts out := by + intro stmt hStmt out hOk + cases hStmt with + | base hBase => + exact compileStmt_internal_body_fragment_bridged fields events errors + dynamicSource internalRetNames inScopeNames hBase hOk + | ite cond thenBranch elseBranch hCond hThen hElse => + simp only [compileStmt, bind, Except.bind] at hOk + cases hCondExpr : compileExpr fields dynamicSource cond with + | error err => + simp [hCondExpr] at hOk + | ok condExpr => + cases hThenCompile : compileStmtList fields events errors dynamicSource + internalRetNames true inScopeNames [] thenBranch with + | error err => + simp [hCondExpr, hThenCompile] at hOk + | ok thenOut => + cases hElseCompile : compileStmtList fields events errors dynamicSource + internalRetNames true inScopeNames [] elseBranch with + | error err => + simp [hCondExpr, hThenCompile, hElseCompile] at hOk + | ok elseOut => + have hCondBridged : BridgedExpr condExpr := + compileExpr_bridgedSource fields dynamicSource hCond hCondExpr + have hThenBridged : BridgedStmts thenOut := + compileStmtList_internal_recursive_body_fragment_bridged fields + events errors dynamicSource internalRetNames hThen + inScopeNames hThenCompile + have hElseBridged : BridgedStmts elseOut := + compileStmtList_internal_recursive_body_fragment_bridged fields + events errors dynamicSource internalRetNames hElse + inScopeNames hElseCompile + by_cases hEmpty : elseBranch.isEmpty + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, + Pure.pure, Except.pure] at hOk + subst out + intro yulStmt hMem + simp only [List.mem_singleton] at hMem + subst yulStmt + exact BridgedStmt.if_ condExpr thenOut hCondBridged hThenBridged + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, + Pure.pure, Except.pure] at hOk + subst out + intro yulStmt hMem + simp only [List.mem_singleton] at hMem + subst yulStmt + refine BridgedStmt.block _ ?_ + intro blockStmt hBlockMem + simp only [List.mem_cons, List.mem_nil_iff] at hBlockMem + rcases hBlockMem with rfl | rfl | rfl | hNil + · exact BridgedStmt.straight _ + (BridgedStraightStmt.let_ _ condExpr hCondBridged) + · exact BridgedStmt.if_ _ thenOut (BridgedExpr.ident _) hThenBridged + · exact BridgedStmt.if_ _ elseOut + (bridgedExpr_iszero_ident _) hElseBridged + · cases hNil + + theorem compileStmtList_internal_recursive_body_fragment_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ {stmts : List Stmt}, + BridgedSourceInternalRecursiveBodyStmts fields dynamicSource stmts → + ∀ (inScopeNames : List String) {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmts = .ok out → BridgedStmts out := by intro stmts hSource inScopeNames out hOk cases hSource with @@ -2441,6 +3723,89 @@ mutual (collectStmtNames head ++ inScopeNames) hTailCompile) end +mutual + theorem compileStmt_internal_recursive_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceInternalRecursiveBodyStmt fields dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | base hBase => + exact compileStmt_internal_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hBase hOk + | ite cond thenBranch elseBranch _ hThen hElse => + simp only [compileStmt, bind, Except.bind] at hOk + cases hCondExpr : compileExpr fields dynamicSource cond with + | error err => simp [hCondExpr] at hOk + | ok condExpr => + cases hThenCompile : compileStmtList fields events errors dynamicSource + internalRetNames true inScopeNames [] thenBranch with + | error err => simp [hCondExpr, hThenCompile] at hOk + | ok thenOut => + cases hElseCompile : compileStmtList fields events errors dynamicSource + internalRetNames true inScopeNames [] elseBranch with + | error err => simp [hCondExpr, hThenCompile, hElseCompile] at hOk + | ok elseOut => + have hThenNoFunc := + compileStmtList_internal_recursive_body_fragment_noFuncDefs fields + events errors dynamicSource internalRetNames hThen inScopeNames + hThenCompile + have hElseNoFunc := + compileStmtList_internal_recursive_body_fragment_noFuncDefs fields + events errors dynamicSource internalRetNames hElse inScopeNames + hElseCompile + by_cases hEmpty : elseBranch.isEmpty + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, + Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc] + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, + Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc, hElseNoFunc] + + theorem compileStmtList_internal_recursive_body_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ {stmts : List Stmt}, + BridgedSourceInternalRecursiveBodyStmts fields dynamicSource stmts → + ∀ (inScopeNames : List String) {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmts hSource inScopeNames out hOk + cases hSource with + | nil => + simp [compileStmtList, Pure.pure, Except.pure] at hOk + subst out + rfl + | @cons head tail hHead hTail => + simp only [compileStmtList, bind, Except.bind] at hOk + cases hHeadCompile : compileStmt fields events errors dynamicSource + internalRetNames true inScopeNames [] head with + | error err => simp [hHeadCompile] at hOk + | ok headOut => + simp [hHeadCompile] at hOk + cases hTailCompile : compileStmtList fields events errors dynamicSource + internalRetNames true (collectStmtNames head ++ inScopeNames) [] tail with + | error err => simp [hTailCompile] at hOk + | ok tailOut => + simp [hTailCompile, Pure.pure, Except.pure] at hOk + subst out + simp [ + compileStmt_internal_recursive_body_fragment_noFuncDefs fields events + errors dynamicSource internalRetNames inScopeNames hHead hHeadCompile, + compileStmtList_internal_recursive_body_fragment_noFuncDefs fields + events errors dynamicSource internalRetNames hTail + (collectStmtNames head ++ inScopeNames) hTailCompile] +end + /-! ## Source statement body closure: direct memory writes (`mstore`/`tstore`) The `Stmt.mstore` and `Stmt.tstore` source statements compile directly to a @@ -2561,6 +3926,58 @@ theorem compileStmtList_memoryWrite_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmt_memoryWrite_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMemoryWriteStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | mstore offset value _ _ => + simp only [compileStmt, bind, Except.bind, Pure.pure, Except.pure] at hOk + cases hO : compileExpr fields dynamicSource offset with + | error err => simp [hO] at hOk + | ok compiledOffset => + simp [hO] at hOk + cases hV : compileExpr fields dynamicSource value with + | error err => simp [hV] at hOk + | ok compiledValue => + simp [hV, Native.yulStmtContainsFuncDef] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + | tstore offset value _ _ => + simp only [compileStmt, bind, Except.bind, Pure.pure, Except.pure] at hOk + cases hO : compileExpr fields dynamicSource offset with + | error err => simp [hO] at hOk + | ok compiledOffset => + simp [hO] at hOk + cases hV : compileExpr fields dynamicSource value with + | error err => simp [hV] at hOk + | ok compiledValue => + simp [hV, Native.yulStmtContainsFuncDef] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + +theorem compileStmtList_memoryWrite_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMemoryWriteStmts stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal BridgedSourceMemoryWriteStmt + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_memoryWrite_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: bounded `forEach` loops The `Stmt.forEach varName count body` source statement compiles to a single @@ -2635,6 +4052,76 @@ theorem compileStmt_forEach_with_bridged_body · -- body exact hBBody +theorem compileStmt_ite_with_noFuncDefs_body + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (cond : Expr) (thenBranch elseBranch : List Stmt) + (hThen : ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] thenBranch = .ok out → + Native.yulStmtsContainFuncDef out = false) + (hElse : ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] elseBranch = .ok out → + Native.yulStmtsContainFuncDef out = false) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.ite cond thenBranch elseBranch) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hCondExpr : compileExpr fields dynamicSource cond with + | error err => simp [hCondExpr] at hOk + | ok condExpr => + cases hThenCompile : compileStmtList fields events errors dynamicSource + internalRetNames isInternal inScopeNames [] thenBranch with + | error err => simp [hCondExpr, hThenCompile] at hOk + | ok thenOut => + cases hElseCompile : compileStmtList fields events errors dynamicSource + internalRetNames isInternal inScopeNames [] elseBranch with + | error err => simp [hCondExpr, hThenCompile, hElseCompile] at hOk + | ok elseOut => + have hThenNoFunc := hThen hThenCompile + have hElseNoFunc := hElse hElseCompile + by_cases hEmpty : elseBranch.isEmpty + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, + Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc] + · simp [hCondExpr, hThenCompile, hElseCompile, hEmpty, + Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hThenNoFunc, hElseNoFunc] + +theorem compileStmt_forEach_with_noFuncDefs_body + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (varName : String) (count : Expr) (body : List Stmt) + (hBody : ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal (varName :: inScopeNames) [] body = .ok out → + Native.yulStmtsContainFuncDef out = false) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.forEach varName count body) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hCExpr : compileExpr fields dynamicSource count with + | error err => simp [hCExpr] at hOk + | ok countExpr => + simp [hCExpr] at hOk + cases hBodyOk : compileStmtList fields events errors dynamicSource + internalRetNames isInternal (varName :: inScopeNames) [] body with + | error err => simp [hBodyOk] at hOk + | ok bodyOut => + have hBodyNoFunc := hBody hBodyOk + simp [hBodyOk, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hBodyNoFunc] + /-! ## Source statement body closure: zero-argument custom errors `Stmt.revertError errorName []` compiles via `revertWithCustomError` to a @@ -2675,6 +4162,20 @@ private theorem sigStores_bridged (sigBytes : List UInt8) : · exact BridgedExpr.lit (idx * 32) · exact BridgedExpr.hex (wordFromBytes chunk) +private theorem sigStores_noFuncDefs (sigBytes : List UInt8) : + Native.yulStmtsContainFuncDef + ((chunkBytes32 sigBytes).zipIdx.map + (fun (chunk, idx) => + YulStmt.expr (YulExpr.call "mstore" [ + YulExpr.call "add" [YulExpr.ident "__err_ptr", YulExpr.lit (idx * 32)], + YulExpr.hex (wordFromBytes chunk)]))) = false := by + induction (chunkBytes32 sigBytes).zipIdx with + | nil => rfl + | cons head tail ih => + cases head with + | mk chunk idx => + simp [Native.yulStmtContainsFuncDef, ih] + /-- A zero-argument custom error reverts via a `.block` whose body is made entirely of bridged straight-line statements. -/ private theorem revertWithCustomError_zero_bridged @@ -2767,6 +4268,41 @@ private theorem revertWithCustomError_zero_bridged subst hRevert exact BridgedStmt.straight _ (BridgedStraightStmt.expr_revert _ _) +private theorem revertWithCustomError_zero_noFuncDefs + (dynamicSource : DynamicDataSource) (errorDef : ErrorDef) + (hParams : errorDef.params = []) : + ∀ {out : List YulStmt}, + revertWithCustomError dynamicSource errorDef [] [] = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + have hNil : (revertWithCustomError dynamicSource errorDef [] []) = .ok + [YulStmt.block + ([YulStmt.let_ "__err_ptr" (YulExpr.call "mload" [YulExpr.lit freeMemoryPointer])] ++ + ((chunkBytes32 (bytesFromString (errorSignature errorDef))).zipIdx.map + (fun (chunk, idx) => + YulStmt.expr (YulExpr.call "mstore" [ + YulExpr.call "add" [YulExpr.ident "__err_ptr", YulExpr.lit (idx * 32)], + YulExpr.hex (wordFromBytes chunk)]))) ++ + [YulStmt.let_ "__err_hash" + (YulExpr.call "keccak256" [YulExpr.ident "__err_ptr", + YulExpr.lit (bytesFromString (errorSignature errorDef)).length]), + YulStmt.let_ "__err_selector" + (YulExpr.call "shl" [YulExpr.lit selectorShift, + YulExpr.call "shr" [YulExpr.lit selectorShift, YulExpr.ident "__err_hash"]]), + YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit 0, YulExpr.ident "__err_selector"]), + YulStmt.let_ "__err_tail" (YulExpr.lit 0)] ++ + [YulStmt.expr (YulExpr.call "revert" + [YulExpr.lit 0, + YulExpr.call "add" [YulExpr.lit 4, YulExpr.ident "__err_tail"]])])] := by + unfold revertWithCustomError + simp [hParams] + rfl + rw [hNil] at hOk + injection hOk with hEq + subst out + simp [Native.yulStmtContainsFuncDef, sigStores_noFuncDefs] + /-- Source custom-error statements with zero parameters whose call-site looks up a defined `ErrorDef` with no parameters. -/ inductive BridgedSourceCustomErrorStmt @@ -2864,8 +4400,71 @@ theorem compileStmt_customError_zero_bridged exact compileStmt_requireError_zero_bridged fields events errors dynamicSource internalRetNames isInternal inScopeNames hLookup hZeroParams hFailCond -/-- A list made entirely of zero-arg custom-error source statements compiles -to a Yul list satisfying `BridgedStmts`. -/ +theorem compileStmt_revertError_zero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + {errorName : String} {errorDef : ErrorDef} + (hLookup : errors.find? (·.name == errorName) = some errorDef) + (hZeroParams : errorDef.params = []) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.revertError errorName []) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind, hLookup, compileExprList, + Pure.pure, Except.pure] at hOk + exact revertWithCustomError_zero_noFuncDefs dynamicSource errorDef hZeroParams hOk + +theorem compileStmt_requireError_zero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + {cond : Expr} {errorName : String} {errorDef : ErrorDef} + (hLookup : errors.find? (·.name == errorName) = some errorDef) + (hZeroParams : errorDef.params = []) + (_hFailCond : ∀ {failCond : YulExpr}, + compileRequireFailCond fields dynamicSource cond = .ok failCond → + BridgedExpr failCond) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.requireError cond errorName []) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hFail : compileRequireFailCond fields dynamicSource cond with + | error err => simp [hFail] at hOk + | ok failCond => + simp [hFail, hLookup, compileExprList, Pure.pure, Except.pure] at hOk + cases hRevert : revertWithCustomError dynamicSource errorDef [] [] with + | error err => simp [hRevert] at hOk + | ok revertStmts => + have hNoFunc := + revertWithCustomError_zero_noFuncDefs dynamicSource errorDef hZeroParams hRevert + simp [hRevert, Native.yulStmtContainsFuncDef, hNoFunc] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, hNoFunc] + +theorem compileStmt_customError_zero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + {stmt : Stmt} + (hStmt : BridgedSourceCustomErrorStmt fields errors dynamicSource stmt) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + cases hStmt with + | revertError errorName errorDef hLookup hZeroParams => + exact compileStmt_revertError_zero_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hLookup hZeroParams + | requireError cond errorName errorDef hLookup hZeroParams hFailCond => + exact compileStmt_requireError_zero_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hLookup hZeroParams hFailCond + +/-- A list made entirely of zero-arg custom-error source statements compiles +to a Yul list satisfying `BridgedStmts`. -/ theorem compileStmtList_customError_zero_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) @@ -2914,6 +4513,23 @@ theorem compileStmtList_customError_zero_bridged · exact hBHead stmt h · exact hBTail stmt h +theorem compileStmtList_customError_zero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceCustomErrorStmts fields errors dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal + (BridgedSourceCustomErrorStmt fields errors dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_customError_zero_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Mixed body with zero-arg custom errors @@ -3023,6 +4639,56 @@ theorem compileStmt_internal_body_with_errors_bridged exact compileStmt_mappingWrite_bridged fields events errors dynamicSource internalRetNames true inScopeNames hMap hOk +theorem compileStmt_external_body_with_errors_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceExternalBodyWithErrorsStmt fields errors dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | base hBase => + exact compileStmt_external_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hBase hOk + | customError hCustom => + exact compileStmt_customError_zero_noFuncDefs fields events errors + dynamicSource internalRetNames false inScopeNames hCustom hOk + | memoryWrite hMem => + exact compileStmt_memoryWrite_noFuncDefs fields events errors dynamicSource + internalRetNames false inScopeNames hMem hOk + | mappingWrite hMap => + exact compileStmt_mappingWrite_noFuncDefs fields events errors dynamicSource + internalRetNames false inScopeNames hMap hOk + +theorem compileStmt_internal_body_with_errors_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceInternalBodyWithErrorsStmt fields errors dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | base hBase => + exact compileStmt_internal_body_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hBase hOk + | customError hCustom => + exact compileStmt_customError_zero_noFuncDefs fields events errors + dynamicSource internalRetNames true inScopeNames hCustom hOk + | memoryWrite hMem => + exact compileStmt_memoryWrite_noFuncDefs fields events errors dynamicSource + internalRetNames true inScopeNames hMem hOk + | mappingWrite hMap => + exact compileStmt_mappingWrite_noFuncDefs fields events errors dynamicSource + internalRetNames true inScopeNames hMap hOk + /-- Mixed external source bodies (storage/require/terminator + zero-arg custom errors) compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_external_body_with_errors_bridged @@ -3076,6 +4742,22 @@ theorem compileStmtList_external_body_with_errors_bridged · exact hBHead stmt h · exact hBTail stmt h +theorem compileStmtList_external_body_with_errors_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceExternalBodyWithErrorsStmts fields errors dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames false + (BridgedSourceExternalBodyWithErrorsStmt fields errors dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_external_body_with_errors_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hStmt hOk) + /-- Mixed internal source bodies (storage/require/returnInternal/stop + zero-arg custom errors) compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_internal_body_with_errors_bridged @@ -3129,6 +4811,22 @@ theorem compileStmtList_internal_body_with_errors_bridged · exact hBHead stmt h · exact hBTail stmt h +theorem compileStmtList_internal_body_with_errors_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceInternalBodyWithErrorsStmts fields errors dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames true + (BridgedSourceInternalBodyWithErrorsStmt fields errors dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_internal_body_with_errors_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hStmt hOk) + /-- A one-layer external `Stmt.ite` whose branches are mixed external with-errors body fragments compiles to bridged Yul. -/ theorem compileStmt_ite_external_body_with_errors_bridged @@ -5644,7 +7342,7 @@ theorem compileStmt_rawLog_bridged compileExpr_bridgedSource fields dynamicSource hSize hSizeExpr have hLenLe : topics.length ≤ 4 := Nat.le_of_not_lt hLen have hLogName : - Compiler.Proofs.IRGeneration.isYulLogName + Compiler.Proofs.YulGeneration.isYulLogName s!"log{topics.length}" = true := by have hn : topics.length ≤ 4 := hLenLe generalize hEq : topics.length = n at hn @@ -5665,6 +7363,41 @@ theorem compileStmt_rawLog_bridged (BridgedStmt.straight _ (BridgedStraightStmt.expr_log _ _ hLogName hArgs)) +/-- Direct `rawLog` source statements compile without nested function +declarations. -/ +theorem compileStmt_rawLog_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceRawLogStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | rawLog topics dataOffset dataSize hTopics hOffset hSize => + simp only [compileStmt] at hOk + by_cases hLen : topics.length > 4 + · simp only [if_pos hLen, bind, Except.bind] at hOk + exact Except.noConfusion hOk + · simp only [if_neg hLen, bind, Except.bind, + Pure.pure, Except.pure] at hOk + cases hTopicsExpr : compileExprList fields dynamicSource topics with + | error err => simp [hTopicsExpr] at hOk + | ok topicExprs => + simp only [hTopicsExpr] at hOk + cases hOffsetExpr : compileExpr fields dynamicSource dataOffset with + | error err => simp [hOffsetExpr] at hOk + | ok offsetExpr => + simp only [hOffsetExpr] at hOk + cases hSizeExpr : compileExpr fields dynamicSource dataSize with + | error err => simp [hSizeExpr] at hOk + | ok sizeExpr => + simp [hSizeExpr, Native.yulStmtContainsFuncDef] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + /-- Lists made only of direct `rawLog` source statements with bridged arguments compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_rawLog_bridged @@ -5709,6 +7442,24 @@ theorem compileStmtList_rawLog_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +/-- Lists made only of direct `rawLog` source statements with bridged +arguments compile without nested function declarations. -/ +theorem compileStmtList_rawLog_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceRawLogStmts stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal BridgedSourceRawLogStmt + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_rawLog_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Mixed body with raw log @@ -5798,6 +7549,44 @@ theorem compileStmt_internal_body_with_raw_log_bridged exact compileStmt_rawLog_bridged fields events errors dynamicSource internalRetNames true inScopeNames hRaw hOk +theorem compileStmt_external_body_with_raw_log_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceExternalBodyWithRawLogStmt fields errors dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | base hBase => + exact compileStmt_external_body_with_errors_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hBase hOk + | rawLog hRaw => + exact compileStmt_rawLog_noFuncDefs fields events errors dynamicSource + internalRetNames false inScopeNames hRaw hOk + +theorem compileStmt_internal_body_with_raw_log_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceInternalBodyWithRawLogStmt fields errors dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | base hBase => + exact compileStmt_internal_body_with_errors_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hBase hOk + | rawLog hRaw => + exact compileStmt_rawLog_noFuncDefs fields events errors dynamicSource + internalRetNames true inScopeNames hRaw hOk + /-- Mixed external source bodies (with-errors fragments + direct `rawLog`) compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_external_body_with_raw_log_bridged @@ -5851,6 +7640,22 @@ theorem compileStmtList_external_body_with_raw_log_bridged · exact hBHead stmt h · exact hBTail stmt h +theorem compileStmtList_external_body_with_raw_log_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceExternalBodyWithRawLogStmts fields errors dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames false + (BridgedSourceExternalBodyWithRawLogStmt fields errors dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_external_body_with_raw_log_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hStmt hOk) + /-- Mixed internal source bodies (with-errors fragments + direct `rawLog`) compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_internal_body_with_raw_log_bridged @@ -5904,6 +7709,22 @@ theorem compileStmtList_internal_body_with_raw_log_bridged · exact hBHead stmt h · exact hBTail stmt h +theorem compileStmtList_internal_body_with_raw_log_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceInternalBodyWithRawLogStmts fields errors dynamicSource stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames true + (BridgedSourceInternalBodyWithRawLogStmt fields errors dynamicSource) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_internal_body_with_raw_log_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hStmt hOk) + /-! ## Recursive mixed body with raw log @@ -6233,29 +8054,169 @@ mutual (collectStmtNames head ++ inScopeNames) hTailCompile) end -/-! ## Source statement body closure: single-slot double-mapping writes - -`Stmt.setMapping2` goes through `compileSetMapping2`, which for a declared -`isMapping2` field with a single write slot emits a single -`sstore(mappingSlot(mappingSlot(lit slot, key1), key2), value)` statement. -This matches `BridgedStraightStmt.expr_sstore_mapping` with the inner -`mappingSlot(lit slot, key1)` as the `baseExpr` argument. The inner -`BridgedExpr` witness is constructed manually via the public -`BridgedExpr.call` ctor since `"mappingSlot" ∈ bridgedBuiltins`. -/ - -/-- Double-mapping-write source statements currently known to compile to -`BridgedStmts`: single-slot writes to a declared `isMapping2` field whose -key1/key2/value expressions are pure `BridgedSourceExpr`s. -/ -inductive BridgedSourceMappingWrite2Stmt (fields : List Field) : Stmt → Prop - | setMapping2 (field : String) {slot : Nat} {key1 key2 value : Expr} - (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) - (hValue : BridgedSourceExpr value) - (hMapping2 : isMapping2 fields field = true) - (hSlots : findFieldWriteSlots fields field = some [slot]) : - BridgedSourceMappingWrite2Stmt fields (.setMapping2 field key1 key2 value) +mutual + theorem compileStmt_external_recursive_body_with_raw_log_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceExternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | base hBase => + exact compileStmt_external_body_with_raw_log_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hBase hOk + | ite cond thenBranch elseBranch _ hThen hElse => + refine compileStmt_ite_with_noFuncDefs_body fields events errors + dynamicSource internalRetNames false inScopeNames cond thenBranch + elseBranch ?_ ?_ hOk + · exact compileStmtList_external_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames hThen inScopeNames + · exact compileStmtList_external_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames hElse inScopeNames + | forEach varName count body _ hBody => + refine compileStmt_forEach_with_noFuncDefs_body fields events errors + dynamicSource internalRetNames false inScopeNames varName count body ?_ hOk + exact compileStmtList_external_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames hBody + (varName :: inScopeNames) + + theorem compileStmtList_external_recursive_body_with_raw_log_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ {stmts : List Stmt}, + BridgedSourceExternalRecursiveBodyWithRawLogStmts fields errors + dynamicSource stmts → + ∀ (inScopeNames : List String) {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmts hSource inScopeNames out hOk + cases hSource with + | nil => + simp [compileStmtList, Pure.pure, Except.pure] at hOk + subst out + rfl + | @cons head tail hHead hTail => + simp only [compileStmtList, bind, Except.bind] at hOk + cases hHeadCompile : compileStmt fields events errors dynamicSource + internalRetNames false inScopeNames [] head with + | error err => simp [hHeadCompile] at hOk + | ok headOut => + simp [hHeadCompile] at hOk + cases hTailCompile : compileStmtList fields events errors dynamicSource + internalRetNames false (collectStmtNames head ++ inScopeNames) [] tail with + | error err => simp [hTailCompile] at hOk + | ok tailOut => + simp [hTailCompile, Pure.pure, Except.pure] at hOk + subst out + simp [ + compileStmt_external_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames + inScopeNames hHead hHeadCompile, + compileStmtList_external_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames hTail + (collectStmtNames head ++ inScopeNames) hTailCompile] +end -def BridgedSourceMappingWrite2Stmts (fields : List Field) (stmts : List Stmt) : Prop := - ∀ stmt ∈ stmts, BridgedSourceMappingWrite2Stmt fields stmt +mutual + theorem compileStmt_internal_recursive_body_with_raw_log_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceInternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | base hBase => + exact compileStmt_internal_body_with_raw_log_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hBase hOk + | ite cond thenBranch elseBranch _ hThen hElse => + refine compileStmt_ite_with_noFuncDefs_body fields events errors + dynamicSource internalRetNames true inScopeNames cond thenBranch + elseBranch ?_ ?_ hOk + · exact compileStmtList_internal_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames hThen inScopeNames + · exact compileStmtList_internal_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames hElse inScopeNames + | forEach varName count body _ hBody => + refine compileStmt_forEach_with_noFuncDefs_body fields events errors + dynamicSource internalRetNames true inScopeNames varName count body ?_ hOk + exact compileStmtList_internal_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames hBody + (varName :: inScopeNames) + + theorem compileStmtList_internal_recursive_body_with_raw_log_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ {stmts : List Stmt}, + BridgedSourceInternalRecursiveBodyWithRawLogStmts fields errors + dynamicSource stmts → + ∀ (inScopeNames : List String) {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmts hSource inScopeNames out hOk + cases hSource with + | nil => + simp [compileStmtList, Pure.pure, Except.pure] at hOk + subst out + rfl + | @cons head tail hHead hTail => + simp only [compileStmtList, bind, Except.bind] at hOk + cases hHeadCompile : compileStmt fields events errors dynamicSource + internalRetNames true inScopeNames [] head with + | error err => simp [hHeadCompile] at hOk + | ok headOut => + simp [hHeadCompile] at hOk + cases hTailCompile : compileStmtList fields events errors dynamicSource + internalRetNames true (collectStmtNames head ++ inScopeNames) [] tail with + | error err => simp [hTailCompile] at hOk + | ok tailOut => + simp [hTailCompile, Pure.pure, Except.pure] at hOk + subst out + simp [ + compileStmt_internal_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames + inScopeNames hHead hHeadCompile, + compileStmtList_internal_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames hTail + (collectStmtNames head ++ inScopeNames) hTailCompile] +end + +/-! ## Source statement body closure: single-slot double-mapping writes + +`Stmt.setMapping2` goes through `compileSetMapping2`, which for a declared +`isMapping2` field with a single write slot emits a single +`sstore(mappingSlot(mappingSlot(lit slot, key1), key2), value)` statement. +This matches `BridgedStraightStmt.expr_sstore_mapping` with the inner +`mappingSlot(lit slot, key1)` as the `baseExpr` argument. The inner +`BridgedExpr` witness is constructed manually via the public +`BridgedExpr.call` ctor since `"mappingSlot" ∈ bridgedBuiltins`. -/ + +/-- Double-mapping-write source statements currently known to compile to +`BridgedStmts`: single-slot writes to a declared `isMapping2` field whose +key1/key2/value expressions are pure `BridgedSourceExpr`s. -/ +inductive BridgedSourceMappingWrite2Stmt (fields : List Field) : Stmt → Prop + | setMapping2 (field : String) {slot : Nat} {key1 key2 value : Expr} + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSourceMappingWrite2Stmt fields (.setMapping2 field key1 key2 value) + +def BridgedSourceMappingWrite2Stmts (fields : List Field) (stmts : List Stmt) : Prop := + ∀ stmt ∈ stmts, BridgedSourceMappingWrite2Stmt fields stmt /-- A single-slot `Stmt.setMapping2` source write with pure bridged key1/ key2/value expressions compiles to `BridgedStmts`. -/ @@ -6328,6 +8289,69 @@ theorem compileStmt_mappingWrite2_bridged dynamicSource internalRetNames isInternal inScopeNames field hKey1 hKey2 hValue hMapping2 hSlots hOk +theorem compileStmt_setMapping2_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key1 key2 value : Expr} + (hMapping2 : isMapping2 fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMapping2 field key1 key2 value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt] at hOk + unfold compileSetMapping2 at hOk + simp [hMapping2, hSlots] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => + simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => + simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + +theorem compileStmt_mappingWrite2_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingWrite2Stmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMapping2 field hKey1 hKey2 hValue hMapping2 hSlots => + exact compileStmt_setMapping2_singleSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field + hMapping2 hSlots hOk + +theorem compileStmtList_mappingWrite2_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingWrite2Stmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMappingWrite2Stmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingWrite2_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-- Lists of single-slot double-mapping-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingWrite2_bridged @@ -6397,6 +8421,23 @@ inductive BridgedSourceStorageAddrStmt (fields : List Field) : Stmt → Prop def BridgedSourceStorageAddrStmts (fields : List Field) (stmts : List Stmt) : Prop := ∀ stmt ∈ stmts, BridgedSourceStorageAddrStmt fields stmt +/-- `SupportedFragment.setStorageAddrSingleSlot` expression and field-layout + witnesses are enough to build the native address-storage source-statement + bridge witness. -/ +theorem bridgedSourceStorageAddrStmt_setStorageAddrSingleSlot_of_exprCompileCore + {fields : List Field} {fieldName : String} {value : Expr} {slot : Nat} + (hValue : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) + (hFind : + findFieldWithResolvedSlot fields fieldName = + some ({ name := fieldName, ty := FieldType.address }, slot)) : + BridgedSourceStorageAddrStmt fields (.setStorageAddr fieldName value) := + BridgedSourceStorageAddrStmt.setStorageAddr fieldName value + { name := fieldName, ty := FieldType.address } slot + (bridgedSourceExpr_of_exprCompileCore hValue) + (isMapping_false_of_findFieldWithResolvedSlot_address hFind rfl) + rfl + (by simpa using hFind) + /-- An address-typed, unpacked single-slot `setStorageAddr` source statement with a pure bridged right-hand side compiles to a literal-slot `sstore(lit slot, and(value, hex addressMask))`, hence satisfies @@ -6505,6 +8546,44 @@ theorem compileStmtList_storageAddr_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmt_storageAddr_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStorageAddrStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setStorageAddr field value f slot hValue hNotMapping hAddrTy hFind => + simp only [compileStmt] at hOk + unfold compileSetStorage at hOk + simp [hNotMapping, hFind, hAddrTy] at hOk + cases hExpr : compileExpr fields dynamicSource value with + | error err => simp [hExpr] at hOk + | ok valueExpr => + simp [hExpr] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + +theorem compileStmtList_storageAddr_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStorageAddrStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceStorageAddrStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_storageAddr_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: single-slot `setStructMember` `Stmt.setStructMember` goes through `compileSetStructMember`, which @@ -6634,132 +8713,717 @@ theorem compileStmtList_structMember_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) -/-! ## Source statement body closure: single-slot `setStructMember2` - -`Stmt.setStructMember2` goes through `compileSetStructMember2`. For an -unpacked, wordOffset=0 member of a single-slot `mappingStruct2` field, -the emitted shape is - `sstore(mappingSlot(mappingSlot(lit slot, key1Expr), key2Expr), valueExpr)` -— identical to single-slot `setMapping2`. Closure mirrors -`compileStmt_setMapping2_singleSlot_bridged` with the added struct -member hypotheses. -/ - -/-- Unpacked, wordOffset=0 setStructMember2 on a single-slot -mappingStruct2 field with pure bridged key1/key2/value. -/ -inductive BridgedSourceStructMember2Stmt (fields : List Field) : Stmt → Prop - | setStructMember2 (field : String) {slot : Nat} {key1 key2 value : Expr} - (memberName : String) (members : List StructMember) (member : StructMember) - (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) - (hValue : BridgedSourceExpr value) - (hMapping2 : isMapping2 fields field = true) - (hMembers : findStructMembers fields field = some members) - (hFindMember : findStructMember members memberName = some member) - (hUnpacked : member.packed = none) - (hWordOffset : member.wordOffset = 0) - (hSlots : findFieldWriteSlots fields field = some [slot]) : - BridgedSourceStructMember2Stmt fields - (.setStructMember2 field key1 key2 memberName value) - -def BridgedSourceStructMember2Stmts (fields : List Field) (stmts : List Stmt) : Prop := - ∀ stmt ∈ stmts, BridgedSourceStructMember2Stmt fields stmt - -/-- A single-slot, unpacked, wordOffset=0 `Stmt.setStructMember2` source -write with pure bridged key1/key2/value expressions compiles to -`BridgedStmts`. -/ -theorem compileStmt_setStructMember2_singleSlot_bridged +theorem compileStmt_setStructMember_singleSlot_noFuncDefs (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) (isInternal : Bool) (inScopeNames : List String) - (field : String) {slot : Nat} {key1 key2 value : Expr} + (field : String) {slot : Nat} {key value : Expr} (memberName : String) (members : List StructMember) (member : StructMember) - (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) - (hValue : BridgedSourceExpr value) - (hMapping2 : isMapping2 fields field = true) + (_hKey : BridgedSourceExpr key) (_hValue : BridgedSourceExpr value) + (hNotMapping2 : isMapping2 fields field = false) (hMembers : findStructMembers fields field = some members) (hFindMember : findStructMember members memberName = some member) (hUnpacked : member.packed = none) (hWordOffset : member.wordOffset = 0) + (hMapping : isMapping fields field = true) (hSlots : findFieldWriteSlots fields field = some [slot]) : ∀ {out : List YulStmt}, compileStmt fields events errors dynamicSource internalRetNames isInternal - inScopeNames [] (.setStructMember2 field key1 key2 memberName value) = .ok out → - BridgedStmts out := by + inScopeNames [] (.setStructMember field key memberName value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by intro out hOk - simp only [compileStmt] at hOk - unfold compileSetStructMember2 at hOk - simp [hMapping2, hMembers, hFindMember, hUnpacked, hWordOffset, hSlots] at hOk - cases hKey1Expr : compileExpr fields dynamicSource key1 with - | error err => simp [hKey1Expr, bind, Except.bind] at hOk - | ok key1Expr => - cases hKey2Expr : compileExpr fields dynamicSource key2 with - | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk - | ok key2Expr => - cases hValueExpr : compileExpr fields dynamicSource value with - | error err => simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk - | ok valueExpr => - simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk - subst hOk - intro yulStmt hMem - simp only [List.mem_singleton] at hMem - subst yulStmt - have hBridgedKey1 : BridgedExpr key1Expr := - compileExpr_bridgedSource fields dynamicSource hKey1 hKey1Expr - have hBridgedKey2 : BridgedExpr key2Expr := - compileExpr_bridgedSource fields dynamicSource hKey2 hKey2Expr - have hBridgedValue : BridgedExpr valueExpr := - compileExpr_bridgedSource fields dynamicSource hValue hValueExpr - have hInnerBridged : BridgedExpr - (Compiler.Yul.YulExpr.call "mappingSlot" - [Compiler.Yul.YulExpr.lit slot, key1Expr]) := by - apply BridgedExpr.call - · exact Or.inl (by decide) - · intro arg hArg - simp only [List.mem_cons, List.not_mem_nil, or_false] at hArg - rcases hArg with hArg | hArg - · subst hArg; exact BridgedExpr.lit slot - · subst hArg; exact hBridgedKey1 - exact BridgedStmt.straight _ - (BridgedStraightStmt.expr_sstore_mapping _ key2Expr valueExpr - hInnerBridged hBridgedKey2 hBridgedValue) + simp only [compileStmt, compileSetStructMember, hNotMapping2, hMembers, + hFindMember, hUnpacked, hWordOffset, bind, Except.bind, + Bool.false_eq_true, if_false] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr, pure, Pure.pure, Except.pure] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr, pure, Pure.pure, Except.pure] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr, pure, Pure.pure, Except.pure] at hOk + exact compileMappingSlotWrite_singleSlot_noFuncDefs fields field + keyExpr valueExpr s!"setStructMember.{memberName}" + hMapping hSlots hOk -/-- Each statement in the struct-member2-write fragment compiles to Yul -satisfying `BridgedStmts`. -/ -theorem compileStmt_structMember2_bridged +theorem compileStmt_structMember_noFuncDefs (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) (isInternal : Bool) (inScopeNames : List String) : - ∀ {stmt : Stmt}, BridgedSourceStructMember2Stmt fields stmt → + ∀ {stmt : Stmt}, BridgedSourceStructMemberStmt fields stmt → ∀ {out : List YulStmt}, compileStmt fields events errors dynamicSource internalRetNames isInternal inScopeNames [] stmt = .ok out → - BridgedStmts out := by + Native.yulStmtsContainFuncDef out = false := by intro stmt hStmt out hOk cases hStmt with - | setStructMember2 field memberName members member hKey1 hKey2 hValue hMapping2 - hMembers hFindMember hUnpacked hWordOffset hSlots => - exact compileStmt_setStructMember2_singleSlot_bridged fields events errors + | setStructMember field memberName members member hKey hValue hNotMapping2 + hMembers hFindMember hUnpacked hWordOffset hMapping hSlots => + exact compileStmt_setStructMember_singleSlot_noFuncDefs fields events errors dynamicSource internalRetNames isInternal inScopeNames field memberName - members member hKey1 hKey2 hValue hMapping2 hMembers hFindMember hUnpacked - hWordOffset hSlots hOk + members member hKey hValue hNotMapping2 hMembers hFindMember hUnpacked + hWordOffset hMapping hSlots hOk -/-- Lists of single-slot struct-member2-write source statements compile -to Yul lists satisfying `BridgedStmts`. -/ -theorem compileStmtList_structMember2_bridged +theorem compileStmtList_structMember_noFuncDefs (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) (isInternal : Bool) : ∀ (stmts : List Stmt) (inScopeNames : List String), - BridgedSourceStructMember2Stmts fields stmts → + BridgedSourceStructMemberStmts fields stmts → ∀ {out : List YulStmt}, compileStmtList fields events errors dynamicSource internalRetNames isInternal inScopeNames [] stmts = .ok out → - BridgedStmts out := by - intro stmts - induction stmts with - | nil => - intro inScopeNames _ out hOk - simp [compileStmtList, Pure.pure, Except.pure] at hOk - subst out + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceStructMemberStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_structMember_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + +private theorem compileMappingSlotWrite_singleSlot_nonzero_bridged + (fields : List Field) (field : String) {slot wordOffset : Nat} + (keyExpr valueExpr : YulExpr) (label : String) + (hKey : BridgedExpr keyExpr) (hValue : BridgedExpr valueExpr) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hNonzero : wordOffset ≠ 0) : + ∀ {out : List YulStmt}, + compileMappingSlotWrite fields field keyExpr valueExpr label wordOffset = .ok out → + BridgedStmts out := by + intro out hOk + have hBeq : (wordOffset == 0) = false := by + cases wordOffset with + | zero => exact absurd rfl hNonzero + | succ n => rfl + simp [compileMappingSlotWrite, hMapping, hSlots, hBeq, Pure.pure, Except.pure] at hOk + subst hOk + intro yulStmt hMem + simp only [List.mem_singleton] at hMem + subst yulStmt + have hMappingExpr : BridgedExpr (.call "mappingSlot" [.lit slot, keyExpr]) := by + refine BridgedExpr.call "mappingSlot" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hArg + simp only [List.mem_cons, List.not_mem_nil, or_false] at hArg + rcases hArg with rfl | rfl + · exact BridgedExpr.lit slot + · exact hKey + exact BridgedStmt.straight _ + (BridgedStraightStmt.expr_sstore_add + (.call "mappingSlot" [.lit slot, keyExpr]) (.lit wordOffset) valueExpr + hMappingExpr (BridgedExpr.lit wordOffset) hValue) + +private theorem compileMappingSlotWrite_singleSlot_nonzero_noFuncDefs + (fields : List Field) (field : String) {slot wordOffset : Nat} + (keyExpr valueExpr : YulExpr) (label : String) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hNonzero : wordOffset ≠ 0) : + ∀ {out : List YulStmt}, + compileMappingSlotWrite fields field keyExpr valueExpr label wordOffset = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + have hBeq : (wordOffset == 0) = false := by + cases wordOffset with + | zero => exact absurd rfl hNonzero + | succ n => rfl + simp [compileMappingSlotWrite, hMapping, hSlots, hBeq, Pure.pure, Except.pure] at hOk + subst hOk + simp [Native.yulStmtContainsFuncDef] + +/-! ## Source statement body closure: single-slot `setStructMember` +(wordOffset ≠ 0) -/ + +/-- Unpacked, wordOffset≠0 setStructMember on a single-slot mappingStruct +field with a pure bridged key and value. -/ +inductive BridgedSourceStructMemberNonzeroStmt (fields : List Field) : + Stmt → Prop + | setStructMember (field : String) {slot : Nat} {key value : Expr} + (memberName : String) (members : List StructMember) (member : StructMember) + (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) + (hNotMapping2 : isMapping2 fields field = false) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hNonzero : member.wordOffset ≠ 0) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSourceStructMemberNonzeroStmt fields + (.setStructMember field key memberName value) + +def BridgedSourceStructMemberNonzeroStmts + (fields : List Field) (stmts : List Stmt) : Prop := + ∀ stmt ∈ stmts, BridgedSourceStructMemberNonzeroStmt fields stmt + +theorem compileStmt_setStructMember_singleSlot_nonzero_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key value : Expr} + (memberName : String) (members : List StructMember) (member : StructMember) + (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) + (hNotMapping2 : isMapping2 fields field = false) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hNonzero : member.wordOffset ≠ 0) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStructMember field key memberName value) = .ok out → + BridgedStmts out := by + intro out hOk + simp only [compileStmt, compileSetStructMember, hNotMapping2, hMembers, + hFindMember, hUnpacked, bind, Except.bind, Bool.false_eq_true, + if_false] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr, pure, Pure.pure, Except.pure] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr, pure, Pure.pure, Except.pure] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr, pure, Pure.pure, Except.pure] at hOk + exact compileMappingSlotWrite_singleSlot_nonzero_bridged fields field + keyExpr valueExpr s!"setStructMember.{memberName}" + (compileExpr_bridgedSource fields dynamicSource hKey hKeyExpr) + (compileExpr_bridgedSource fields dynamicSource hValue hValueExpr) + hMapping hSlots hNonzero hOk + +theorem compileStmt_structMemberNonzero_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStructMemberNonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + BridgedStmts out := by + intro stmt hStmt out hOk + cases hStmt with + | setStructMember field memberName members member hKey hValue hNotMapping2 + hMembers hFindMember hUnpacked hNonzero hMapping hSlots => + exact compileStmt_setStructMember_singleSlot_nonzero_bridged fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + memberName members member hKey hValue hNotMapping2 hMembers hFindMember + hUnpacked hNonzero hMapping hSlots hOk + +theorem compileStmt_setStructMember_singleSlot_nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key value : Expr} + (memberName : String) (members : List StructMember) (member : StructMember) + (_hKey : BridgedSourceExpr key) (_hValue : BridgedSourceExpr value) + (hNotMapping2 : isMapping2 fields field = false) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hNonzero : member.wordOffset ≠ 0) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStructMember field key memberName value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, compileSetStructMember, hNotMapping2, hMembers, + hFindMember, hUnpacked, bind, Except.bind, Bool.false_eq_true, + if_false] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr, pure, Pure.pure, Except.pure] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr, pure, Pure.pure, Except.pure] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr, pure, Pure.pure, Except.pure] at hOk + exact compileMappingSlotWrite_singleSlot_nonzero_noFuncDefs fields field + keyExpr valueExpr s!"setStructMember.{memberName}" + hMapping hSlots hNonzero hOk + +theorem compileStmt_structMemberNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStructMemberNonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setStructMember field memberName members member hKey hValue hNotMapping2 + hMembers hFindMember hUnpacked hNonzero hMapping hSlots => + exact compileStmt_setStructMember_singleSlot_nonzero_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + memberName members member hKey hValue hNotMapping2 hMembers hFindMember + hUnpacked hNonzero hMapping hSlots hOk + +theorem compileStmtList_structMemberNonzero_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStructMemberNonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + BridgedStmts out := by + intro stmts + induction stmts with + | nil => + intro inScopeNames _ out hOk + simp [compileStmtList, Pure.pure, Except.pure] at hOk + subst out + intro stmt hMem + cases hMem + | cons head tail ih => + intro inScopeNames hSource out hOk + simp only [compileStmtList, bind, Except.bind] at hOk + cases hHead : compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] head with + | error err => simp [hHead] at hOk + | ok headOut => + simp [hHead] at hOk + cases hTail : compileStmtList fields events errors dynamicSource + internalRetNames isInternal (collectStmtNames head ++ inScopeNames) [] tail with + | error err => simp [hTail] at hOk + | ok tailOut => + simp [hTail, Pure.pure, Except.pure] at hOk + subst out + have hHeadSource : BridgedSourceStructMemberNonzeroStmt fields head := + hSource head (by simp) + have hTailSource : BridgedSourceStructMemberNonzeroStmts fields tail := by + intro stmt hMem + exact hSource stmt (by simp [hMem]) + exact BridgedStmts_append + (compileStmt_structMemberNonzero_bridged fields events errors + dynamicSource internalRetNames isInternal inScopeNames + hHeadSource hHead) + (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) + +theorem compileStmtList_structMemberNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStructMemberNonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceStructMemberNonzeroStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_structMemberNonzero_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + +/-! ## Source statement body closure: single-slot `setStructMember2` + +`Stmt.setStructMember2` goes through `compileSetStructMember2`. For an +unpacked, wordOffset=0 member of a single-slot `mappingStruct2` field, +the emitted shape is + `sstore(mappingSlot(mappingSlot(lit slot, key1Expr), key2Expr), valueExpr)` +— identical to single-slot `setMapping2`. Closure mirrors +`compileStmt_setMapping2_singleSlot_bridged` with the added struct +member hypotheses. -/ + +/-- Unpacked, wordOffset=0 setStructMember2 on a single-slot +mappingStruct2 field with pure bridged key1/key2/value. -/ +inductive BridgedSourceStructMember2Stmt (fields : List Field) : Stmt → Prop + | setStructMember2 (field : String) {slot : Nat} {key1 key2 value : Expr} + (memberName : String) (members : List StructMember) (member : StructMember) + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hWordOffset : member.wordOffset = 0) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSourceStructMember2Stmt fields + (.setStructMember2 field key1 key2 memberName value) + +def BridgedSourceStructMember2Stmts (fields : List Field) (stmts : List Stmt) : Prop := + ∀ stmt ∈ stmts, BridgedSourceStructMember2Stmt fields stmt + +/-- A single-slot, unpacked, wordOffset=0 `Stmt.setStructMember2` source +write with pure bridged key1/key2/value expressions compiles to +`BridgedStmts`. -/ +theorem compileStmt_setStructMember2_singleSlot_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key1 key2 value : Expr} + (memberName : String) (members : List StructMember) (member : StructMember) + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hWordOffset : member.wordOffset = 0) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStructMember2 field key1 key2 memberName value) = .ok out → + BridgedStmts out := by + intro out hOk + simp only [compileStmt] at hOk + unfold compileSetStructMember2 at hOk + simp [hMapping2, hMembers, hFindMember, hUnpacked, hWordOffset, hSlots] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst hOk + intro yulStmt hMem + simp only [List.mem_singleton] at hMem + subst yulStmt + have hBridgedKey1 : BridgedExpr key1Expr := + compileExpr_bridgedSource fields dynamicSource hKey1 hKey1Expr + have hBridgedKey2 : BridgedExpr key2Expr := + compileExpr_bridgedSource fields dynamicSource hKey2 hKey2Expr + have hBridgedValue : BridgedExpr valueExpr := + compileExpr_bridgedSource fields dynamicSource hValue hValueExpr + have hInnerBridged : BridgedExpr + (Compiler.Yul.YulExpr.call "mappingSlot" + [Compiler.Yul.YulExpr.lit slot, key1Expr]) := by + apply BridgedExpr.call + · exact Or.inl (by decide) + · intro arg hArg + simp only [List.mem_cons, List.not_mem_nil, or_false] at hArg + rcases hArg with hArg | hArg + · subst hArg; exact BridgedExpr.lit slot + · subst hArg; exact hBridgedKey1 + exact BridgedStmt.straight _ + (BridgedStraightStmt.expr_sstore_mapping _ key2Expr valueExpr + hInnerBridged hBridgedKey2 hBridgedValue) + +/-- Each statement in the struct-member2-write fragment compiles to Yul +satisfying `BridgedStmts`. -/ +theorem compileStmt_structMember2_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStructMember2Stmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + BridgedStmts out := by + intro stmt hStmt out hOk + cases hStmt with + | setStructMember2 field memberName members member hKey1 hKey2 hValue hMapping2 + hMembers hFindMember hUnpacked hWordOffset hSlots => + exact compileStmt_setStructMember2_singleSlot_bridged fields events errors + dynamicSource internalRetNames isInternal inScopeNames field memberName + members member hKey1 hKey2 hValue hMapping2 hMembers hFindMember hUnpacked + hWordOffset hSlots hOk + +/-- Lists of single-slot struct-member2-write source statements compile +to Yul lists satisfying `BridgedStmts`. -/ +theorem compileStmtList_structMember2_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStructMember2Stmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + BridgedStmts out := by + intro stmts + induction stmts with + | nil => + intro inScopeNames _ out hOk + simp [compileStmtList, Pure.pure, Except.pure] at hOk + subst out + intro stmt hMem + cases hMem + | cons head tail ih => + intro inScopeNames hSource out hOk + simp only [compileStmtList, bind, Except.bind] at hOk + cases hHead : compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] head with + | error err => simp [hHead] at hOk + | ok headOut => + simp [hHead] at hOk + cases hTail : compileStmtList fields events errors dynamicSource + internalRetNames isInternal (collectStmtNames head ++ inScopeNames) [] tail with + | error err => simp [hTail] at hOk + | ok tailOut => + simp [hTail, Pure.pure, Except.pure] at hOk + subst out + have hHeadSource : BridgedSourceStructMember2Stmt fields head := + hSource head (by simp) + have hTailSource : BridgedSourceStructMember2Stmts fields tail := by + intro stmt hMem + exact hSource stmt (by simp [hMem]) + exact BridgedStmts_append + (compileStmt_structMember2_bridged fields events errors dynamicSource + internalRetNames isInternal inScopeNames hHeadSource hHead) + (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) + +theorem compileStmt_setStructMember2_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key1 key2 value : Expr} + (memberName : String) (members : List StructMember) (member : StructMember) + (_hKey1 : BridgedSourceExpr key1) (_hKey2 : BridgedSourceExpr key2) + (_hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hWordOffset : member.wordOffset = 0) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStructMember2 field key1 key2 memberName value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt] at hOk + unfold compileSetStructMember2 at hOk + simp [hMapping2, hMembers, hFindMember, hUnpacked, hWordOffset, hSlots] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst hOk + simp [Native.yulStmtContainsFuncDef] + +theorem compileStmt_structMember2_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStructMember2Stmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setStructMember2 field memberName members member hKey1 hKey2 hValue hMapping2 + hMembers hFindMember hUnpacked hWordOffset hSlots => + exact compileStmt_setStructMember2_singleSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field memberName + members member hKey1 hKey2 hValue hMapping2 hMembers hFindMember hUnpacked + hWordOffset hSlots hOk + +theorem compileStmtList_structMember2_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStructMember2Stmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceStructMember2Stmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_structMember2_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + +/-! ## Source statement body closure: single-slot `setStructMember2` +(wordOffset ≠ 0) -/ + +/-- Unpacked, wordOffset≠0 setStructMember2 on a single-slot mappingStruct2 +field with pure bridged key1/key2/value. -/ +inductive BridgedSourceStructMember2NonzeroStmt (fields : List Field) : + Stmt → Prop + | setStructMember2 (field : String) {slot : Nat} {key1 key2 value : Expr} + (memberName : String) (members : List StructMember) (member : StructMember) + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hNonzero : member.wordOffset ≠ 0) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSourceStructMember2NonzeroStmt fields + (.setStructMember2 field key1 key2 memberName value) + +def BridgedSourceStructMember2NonzeroStmts + (fields : List Field) (stmts : List Stmt) : Prop := + ∀ stmt ∈ stmts, BridgedSourceStructMember2NonzeroStmt fields stmt + +theorem compileStmt_setStructMember2_singleSlot_nonzero_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key1 key2 value : Expr} + (memberName : String) (members : List StructMember) (member : StructMember) + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hNonzero : member.wordOffset ≠ 0) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStructMember2 field key1 key2 memberName value) = .ok out → + BridgedStmts out := by + intro out hOk + have hBeq : (member.wordOffset == 0) = false := by + rw [beq_eq_false_iff_ne] + exact hNonzero + simp only [compileStmt] at hOk + unfold compileSetStructMember2 at hOk + simp [hMapping2, hMembers, hFindMember, hUnpacked, hBeq, hSlots] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst hOk + intro yulStmt hMem + simp only [List.mem_singleton] at hMem + subst yulStmt + have hBridgedKey1 : BridgedExpr key1Expr := + compileExpr_bridgedSource fields dynamicSource hKey1 hKey1Expr + have hBridgedKey2 : BridgedExpr key2Expr := + compileExpr_bridgedSource fields dynamicSource hKey2 hKey2Expr + have hBridgedValue : BridgedExpr valueExpr := + compileExpr_bridgedSource fields dynamicSource hValue hValueExpr + have hInnerBridged : BridgedExpr + (Compiler.Yul.YulExpr.call "mappingSlot" + [Compiler.Yul.YulExpr.lit slot, key1Expr]) := by + refine BridgedExpr.call "mappingSlot" _ + (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hArg + simp only [List.mem_cons, List.not_mem_nil, or_false] at hArg + rcases hArg with rfl | rfl + · exact BridgedExpr.lit slot + · exact hBridgedKey1 + have hOuterBridged : BridgedExpr + (Compiler.Yul.YulExpr.call "mappingSlot" + [Compiler.Yul.YulExpr.call "mappingSlot" + [Compiler.Yul.YulExpr.lit slot, key1Expr], + key2Expr]) := by + refine BridgedExpr.call "mappingSlot" _ + (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hArg + simp only [List.mem_cons, List.not_mem_nil, or_false] at hArg + rcases hArg with rfl | rfl + · exact hInnerBridged + · exact hBridgedKey2 + exact BridgedStmt.straight _ + (BridgedStraightStmt.expr_sstore_add _ (.lit member.wordOffset) + valueExpr hOuterBridged (BridgedExpr.lit member.wordOffset) + hBridgedValue) + +theorem compileStmt_structMember2Nonzero_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStructMember2NonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + BridgedStmts out := by + intro stmt hStmt out hOk + cases hStmt with + | setStructMember2 field memberName members member hKey1 hKey2 hValue + hMapping2 hMembers hFindMember hUnpacked hNonzero hSlots => + exact compileStmt_setStructMember2_singleSlot_nonzero_bridged fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + memberName members member hKey1 hKey2 hValue hMapping2 hMembers + hFindMember hUnpacked hNonzero hSlots hOk + +theorem compileStmt_setStructMember2_singleSlot_nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key1 key2 value : Expr} + (memberName : String) (members : List StructMember) (member : StructMember) + (_hKey1 : BridgedSourceExpr key1) (_hKey2 : BridgedSourceExpr key2) + (_hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hNonzero : member.wordOffset ≠ 0) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStructMember2 field key1 key2 memberName value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + have hBeq : (member.wordOffset == 0) = false := by + rw [beq_eq_false_iff_ne] + exact hNonzero + simp only [compileStmt] at hOk + unfold compileSetStructMember2 at hOk + simp [hMapping2, hMembers, hFindMember, hUnpacked, hBeq, hSlots] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst hOk + simp [Native.yulStmtContainsFuncDef] + +theorem compileStmt_structMember2Nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStructMember2NonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setStructMember2 field memberName members member hKey1 hKey2 hValue + hMapping2 hMembers hFindMember hUnpacked hNonzero hSlots => + exact compileStmt_setStructMember2_singleSlot_nonzero_noFuncDefs fields + events errors dynamicSource internalRetNames isInternal inScopeNames + field memberName members member hKey1 hKey2 hValue hMapping2 hMembers + hFindMember hUnpacked hNonzero hSlots hOk + +theorem compileStmtList_structMember2Nonzero_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStructMember2NonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + BridgedStmts out := by + intro stmts + induction stmts with + | nil => + intro inScopeNames _ out hOk + simp [compileStmtList, Pure.pure, Except.pure] at hOk + subst out intro stmt hMem cases hMem | cons head tail ih => @@ -6776,16 +9440,35 @@ theorem compileStmtList_structMember2_bridged | ok tailOut => simp [hTail, Pure.pure, Except.pure] at hOk subst out - have hHeadSource : BridgedSourceStructMember2Stmt fields head := + have hHeadSource : + BridgedSourceStructMember2NonzeroStmt fields head := hSource head (by simp) - have hTailSource : BridgedSourceStructMember2Stmts fields tail := by + have hTailSource : + BridgedSourceStructMember2NonzeroStmts fields tail := by intro stmt hMem exact hSource stmt (by simp [hMem]) exact BridgedStmts_append - (compileStmt_structMember2_bridged fields events errors dynamicSource - internalRetNames isInternal inScopeNames hHeadSource hHead) + (compileStmt_structMember2Nonzero_bridged fields events errors + dynamicSource internalRetNames isInternal inScopeNames + hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_structMember2Nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStructMember2NonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceStructMember2NonzeroStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_structMember2Nonzero_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: single-slot `setMappingWord` (wordOffset=0) @@ -6904,6 +9587,64 @@ theorem compileStmtList_mappingWord_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmt_setMappingWord_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key value : Expr} (wordOffset : Nat) + (_hKey : BridgedSourceExpr key) (_hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hWordOffset : wordOffset = 0) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMappingWord field key wordOffset value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + subst hWordOffset + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr] at hOk + exact compileMappingSlotWrite_singleSlot_noFuncDefs fields field + keyExpr valueExpr "setMappingWord" hMapping hSlots hOk + +theorem compileStmt_mappingWord_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingWordStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMappingWord field wordOffset hKey hValue hMapping hSlots hWordOffset => + exact compileStmt_setMappingWord_singleSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field wordOffset + hKey hValue hMapping hSlots hWordOffset hOk + +theorem compileStmtList_mappingWord_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingWordStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMappingWordStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingWord_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: single-slot `setMapping2Word` (wordOffset=0) @@ -7047,6 +9788,71 @@ theorem compileStmtList_mapping2Word_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmt_setMapping2Word_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key1 key2 value : Expr} (wordOffset : Nat) + (_hKey1 : BridgedSourceExpr key1) (_hKey2 : BridgedSourceExpr key2) + (_hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hWordOffset : wordOffset = 0) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMapping2Word field key1 key2 wordOffset value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + subst hWordOffset + simp only [compileStmt] at hOk + unfold compileSetMapping2Word at hOk + simp [hMapping2, hSlots] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst hOk + simp [Native.yulStmtContainsFuncDef] + +theorem compileStmt_mapping2Word_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMapping2WordStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMapping2Word field wordOffset hKey1 hKey2 hValue hMapping2 hSlots + hWordOffset => + exact compileStmt_setMapping2Word_singleSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field wordOffset + hKey1 hKey2 hValue hMapping2 hSlots hWordOffset hOk + +theorem compileStmtList_mapping2Word_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMapping2WordStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMapping2WordStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mapping2Word_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: external `returnValues []` `Stmt.returnValues []` with `isInternal = false` compiles to @@ -7082,6 +9888,20 @@ private theorem compileStmt_returnValuesEmpty_external_bridged (BridgedStraightStmt.expr_return (.lit 0) (.lit 0) (BridgedExpr.lit 0) (BridgedExpr.lit 0)) +private theorem compileStmt_returnValuesEmpty_external_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] (.returnValues []) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp [compileStmt, Pure.pure, Except.pure, Native.yulStmtContainsFuncDef] + at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + /-- Each statement in the empty-returnValues external fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_returnValuesEmpty_bridged @@ -7099,6 +9919,21 @@ theorem compileStmt_returnValuesEmpty_bridged exact compileStmt_returnValuesEmpty_external_bridged fields events errors dynamicSource internalRetNames inScopeNames hOk +theorem compileStmt_returnValuesEmpty_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceReturnValuesEmptyStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | returnValuesEmpty => + exact compileStmt_returnValuesEmpty_external_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hOk + /-- Lists of external empty-returnValues source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_returnValuesEmpty_bridged @@ -7142,6 +9977,21 @@ theorem compileStmtList_returnValuesEmpty_bridged dynamicSource internalRetNames inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_returnValuesEmpty_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceReturnValuesEmptyStmts stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames false BridgedSourceReturnValuesEmptyStmt + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_returnValuesEmpty_noFuncDefs fields events errors dynamicSource + internalRetNames inScopeNames hStmt hOk) + /-! ## Source statement body closure: internal `returnValues []` `Stmt.returnValues []` with `isInternal = true` and `internalRetNames = []` @@ -7175,6 +10025,19 @@ private theorem compileStmt_returnValuesEmpty_internal_bridged subst yulStmt exact BridgedStmt.straight _ BridgedStraightStmt.leave +private theorem compileStmt_returnValuesEmpty_internal_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (inScopeNames : List String) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource (internalRetNames := []) + (isInternal := true) inScopeNames [] (.returnValues []) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp [compileStmt, compileExprList, bind, Except.bind, Pure.pure, + Except.pure, Native.yulStmtContainsFuncDef] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + /-- Each statement in the empty-returnValues internal fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_returnValuesEmpty_internal_fragment_bridged @@ -7191,6 +10054,20 @@ theorem compileStmt_returnValuesEmpty_internal_fragment_bridged exact compileStmt_returnValuesEmpty_internal_bridged fields events errors dynamicSource inScopeNames hOk +theorem compileStmt_returnValuesEmpty_internal_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceReturnValuesEmptyInternalStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource (internalRetNames := []) + (isInternal := true) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | returnValuesEmptyInternal => + exact compileStmt_returnValuesEmpty_internal_noFuncDefs fields events errors + dynamicSource inScopeNames hOk + /-- Lists of internal empty-returnValues source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_returnValuesEmpty_internal_bridged @@ -7234,6 +10111,21 @@ theorem compileStmtList_returnValuesEmpty_internal_bridged errors dynamicSource inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_returnValuesEmpty_internal_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceReturnValuesEmptyInternalStmts stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource (internalRetNames := []) + (isInternal := true) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + [] true BridgedSourceReturnValuesEmptyInternalStmt + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_returnValuesEmpty_internal_fragment_noFuncDefs fields events + errors dynamicSource inScopeNames hStmt hOk) + /-! ## Source statement body closure: internal non-empty `returnValues` `Stmt.returnValues values` with `isInternal = true` and @@ -7292,6 +10184,22 @@ private theorem zip_assigns_bridgedStmts (names : List String) : | inr h => exact ih cs hCs stmt h +private theorem zip_assigns_noFuncDefs (names : List String) : + ∀ (compiled : List YulExpr), + Native.yulStmtsContainFuncDef + ((names.zip compiled).map (fun p => YulStmt.assign p.1 p.2)) = false := by + induction names with + | nil => + intro compiled + simp [Native.yulStmtsContainFuncDef] + | cons n ns ih => + intro compiled + cases compiled with + | nil => + simp [Native.yulStmtsContainFuncDef] + | cons c cs => + simp [Native.yulStmtContainsFuncDef, ih cs] + /-- An internal non-empty `Stmt.returnValues values` with matching arity and bridged source value expressions compiles to a Yul list satisfying `BridgedStmts`. -/ @@ -7321,9 +10229,47 @@ private theorem compileStmt_returnValuesInternal_bridged (zip_assigns_bridgedStmts internalRetNames compiled hAllBridged) (BridgedStmt.straight _ BridgedStraightStmt.leave) -/-- Each statement in the internal-non-empty-`returnValues` fragment -compiles to Yul satisfying `BridgedStmts`. -/ -theorem compileStmt_returnValuesInternal_fragment_bridged +private theorem compileStmt_returnValuesInternal_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) (values : List Expr) + (hLen : values.length = internalRetNames.length) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] (.returnValues values) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + have hLenFalse : (values.length != internalRetNames.length) = false := by + simp [hLen] + simp only [compileStmt, hLenFalse, bind, Except.bind, + Pure.pure, Except.pure] at hOk + cases hCompiled : compileExprList fields dynamicSource values with + | error err => simp [hCompiled] at hOk + | ok compiled => + simp [hCompiled, Native.yulStmtContainsFuncDef] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, + zip_assigns_noFuncDefs internalRetNames compiled] + +/-- Each statement in the internal-non-empty-`returnValues` fragment +compiles to Yul satisfying `BridgedStmts`. -/ +theorem compileStmt_returnValuesInternal_fragment_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceReturnValuesInternalStmt internalRetNames stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmt = .ok out → + BridgedStmts out := by + intro stmt hStmt out hOk + cases hStmt with + | returnValuesInternal values hValues hLen => + exact compileStmt_returnValuesInternal_bridged fields events errors + dynamicSource internalRetNames inScopeNames values hValues hLen hOk + +theorem compileStmt_returnValuesInternal_fragment_noFuncDefs (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) (inScopeNames : List String) : @@ -7332,12 +10278,12 @@ theorem compileStmt_returnValuesInternal_fragment_bridged ∀ {out : List YulStmt}, compileStmt fields events errors dynamicSource internalRetNames (isInternal := true) inScopeNames [] stmt = .ok out → - BridgedStmts out := by + Native.yulStmtsContainFuncDef out = false := by intro stmt hStmt out hOk cases hStmt with | returnValuesInternal values hValues hLen => - exact compileStmt_returnValuesInternal_bridged fields events errors - dynamicSource internalRetNames inScopeNames values hValues hLen hOk + exact compileStmt_returnValuesInternal_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames values hLen hOk /-- Lists of internal non-empty `returnValues` source statements (all sharing the same `internalRetNames` arity) compile to Yul lists satisfying @@ -7385,6 +10331,21 @@ theorem compileStmtList_returnValuesInternal_bridged dynamicSource internalRetNames inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_returnValuesInternal_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceReturnValuesInternalStmts internalRetNames stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := true) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames true (BridgedSourceReturnValuesInternalStmt internalRetNames) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_returnValuesInternal_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hStmt hOk) + /-! ## Source statement body closure: external general `returnValues` `Stmt.returnValues values` with `isInternal = false` compiles to: @@ -7445,6 +10406,21 @@ private theorem zipIdx_mstores_bridgedStmts : | inr h => exact ih (startIdx + 1) hCs stmt h +private theorem zipIdx_mstores_noFuncDefs : + ∀ (compiled : List YulExpr) (startIdx : Nat), + Native.yulStmtsContainFuncDef + ((compiled.zipIdx startIdx).map (fun p => + YulStmt.expr (YulExpr.call "mstore" + [YulExpr.lit (p.2 * 32), p.1]))) = false := by + intro compiled + induction compiled with + | nil => + intro startIdx + simp [Native.yulStmtsContainFuncDef] + | cons c cs ih => + intro startIdx + simp [List.zipIdx_cons, Native.yulStmtContainsFuncDef, ih (startIdx + 1)] + /-- An external `Stmt.returnValues values` (for any `values`) with bridged source value expressions compiles to a Yul list satisfying `BridgedStmts`. -/ private theorem compileStmt_returnValuesExternal_bridged @@ -7484,6 +10460,32 @@ private theorem compileStmt_returnValuesExternal_bridged (BridgedStraightStmt.expr_return (.lit 0) (.lit (values.length * 32)) (BridgedExpr.lit 0) (BridgedExpr.lit (values.length * 32)))) +private theorem compileStmt_returnValuesExternal_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) (values : List Expr) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] (.returnValues values) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + by_cases hValuesNil : values = [] + · subst hValuesNil + simp [compileStmt, Pure.pure, Except.pure, Native.yulStmtContainsFuncDef] + at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + · have hEmptyFalse : values.isEmpty = false := by + simp [hValuesNil] + simp only [compileStmt, hEmptyFalse, bind, Except.bind, + Pure.pure, Except.pure] at hOk + cases hCompiled : compileExprList fields dynamicSource values with + | error err => simp [hCompiled] at hOk + | ok compiled => + simp [hCompiled, Native.yulStmtContainsFuncDef] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, zipIdx_mstores_noFuncDefs compiled 0] + /-- Each statement in the external-`returnValues` fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_returnValuesExternal_fragment_bridged @@ -7501,6 +10503,21 @@ theorem compileStmt_returnValuesExternal_fragment_bridged exact compileStmt_returnValuesExternal_bridged fields events errors dynamicSource internalRetNames inScopeNames values hValues hOk +theorem compileStmt_returnValuesExternal_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceReturnValuesExternalStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | returnValuesExternal values hValues => + exact compileStmt_returnValuesExternal_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames values hOk + /-- Lists of external `returnValues` source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_returnValuesExternal_bridged @@ -7545,6 +10562,21 @@ theorem compileStmtList_returnValuesExternal_bridged hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_returnValuesExternal_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceReturnValuesExternalStmts stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + (isInternal := false) inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames false BridgedSourceReturnValuesExternalStmt + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_returnValuesExternal_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames inScopeNames hStmt hOk) + /-! ## Source statement body closure: mstore / tstore `Stmt.mstore offset value` compiles to @@ -7564,6 +10596,17 @@ inductive BridgedSourceMstoreStmt : Stmt → Prop def BridgedSourceMstoreStmts (stmts : List Stmt) : Prop := ∀ stmt ∈ stmts, BridgedSourceMstoreStmt stmt +/-- `SupportedFragment.mstoreSingle` expression witnesses are enough to build + the native mstore source-statement bridge witness. -/ +theorem bridgedSourceMstoreStmt_of_exprCompileCore + {offset value : Expr} + (hOffset : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hValue : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) : + BridgedSourceMstoreStmt (.mstore offset value) := + BridgedSourceMstoreStmt.mstore offset value + (bridgedSourceExpr_of_exprCompileCore hOffset) + (bridgedSourceExpr_of_exprCompileCore hValue) + private theorem compileStmt_mstore_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) @@ -7595,6 +10638,28 @@ private theorem compileStmt_mstore_bridged exact BridgedStmt.straight _ (BridgedStraightStmt.expr_mstore compiledOffset compiledValue hBO hBV) +private theorem compileStmt_mstore_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (offset value : Expr) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] (.mstore offset value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind, Pure.pure, Except.pure] at hOk + cases hO : compileExpr fields dynamicSource offset with + | error err => simp [hO] at hOk + | ok compiledOffset => + simp [hO] at hOk + cases hV : compileExpr fields dynamicSource value with + | error err => simp [hV] at hOk + | ok compiledValue => + simp [hV, Native.yulStmtContainsFuncDef] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + theorem compileStmt_mstore_fragment_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) @@ -7610,6 +10675,21 @@ theorem compileStmt_mstore_fragment_bridged exact compileStmt_mstore_bridged fields events errors dynamicSource internalRetNames isInternal inScopeNames offset value hOffset hValue hOk +theorem compileStmt_mstore_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMstoreStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | mstore offset value hOffset hValue => + exact compileStmt_mstore_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames offset value hOk + theorem compileStmtList_mstore_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) @@ -7653,6 +10733,22 @@ theorem compileStmtList_mstore_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mstore_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMstoreStmts stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal BridgedSourceMstoreStmt + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mstore_fragment_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + inductive BridgedSourceTstoreStmt : Stmt → Prop | tstore (offset value : Expr) (hOffset : BridgedSourceExpr offset) @@ -7662,6 +10758,17 @@ inductive BridgedSourceTstoreStmt : Stmt → Prop def BridgedSourceTstoreStmts (stmts : List Stmt) : Prop := ∀ stmt ∈ stmts, BridgedSourceTstoreStmt stmt +/-- `SupportedFragment.tstoreSingle` expression witnesses are enough to build + the native tstore source-statement bridge witness. -/ +theorem bridgedSourceTstoreStmt_of_exprCompileCore + {offset value : Expr} + (hOffset : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hValue : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) : + BridgedSourceTstoreStmt (.tstore offset value) := + BridgedSourceTstoreStmt.tstore offset value + (bridgedSourceExpr_of_exprCompileCore hOffset) + (bridgedSourceExpr_of_exprCompileCore hValue) + private theorem compileStmt_tstore_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) @@ -7693,6 +10800,28 @@ private theorem compileStmt_tstore_bridged exact BridgedStmt.straight _ (BridgedStraightStmt.expr_tstore compiledOffset compiledValue hBO hBV) +private theorem compileStmt_tstore_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (offset value : Expr) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] (.tstore offset value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind, Pure.pure, Except.pure] at hOk + cases hO : compileExpr fields dynamicSource offset with + | error err => simp [hO] at hOk + | ok compiledOffset => + simp [hO] at hOk + cases hV : compileExpr fields dynamicSource value with + | error err => simp [hV] at hOk + | ok compiledValue => + simp [hV, Native.yulStmtContainsFuncDef] at hOk + subst out + simp [Native.yulStmtContainsFuncDef] + theorem compileStmt_tstore_fragment_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) @@ -7708,6 +10837,21 @@ theorem compileStmt_tstore_fragment_bridged exact compileStmt_tstore_bridged fields events errors dynamicSource internalRetNames isInternal inScopeNames offset value hOffset hValue hOk +theorem compileStmt_tstore_fragment_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceTstoreStmt stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | tstore offset value hOffset hValue => + exact compileStmt_tstore_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames offset value hOk + theorem compileStmtList_tstore_bridged (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) @@ -7751,6 +10895,22 @@ theorem compileStmtList_tstore_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_tstore_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceTstoreStmts stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal BridgedSourceTstoreStmt + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_tstore_fragment_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: `storageArrayPush` `Stmt.storageArrayPush field value` compiles via `compileStorageArrayPush` @@ -7847,6 +11007,30 @@ theorem compileStmt_storageArrayPush_singleSlot_bridged (BridgedExpr.ident "__array_len") hValBridged · exact BridgedStraightStmt.expr_sstore_lit slot _ hAddLen1 +private theorem compileStmt_storageArrayPush_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) (value : Expr) (f : Field) (slot : Nat) + (elemType : StorageArrayElemType) + (hFind : findFieldWithResolvedSlot fields field = some (f, slot)) + (hDynArr : f.ty = .dynamicArray elemType) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.storageArrayPush field value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt] at hOk + unfold compileStorageArrayPush at hOk + unfold validateDynamicArrayField at hOk + simp [hFind, hDynArr, bind, Except.bind] at hOk + cases hExpr : compileExpr fields dynamicSource value with + | error err => simp [hExpr, Pure.pure, Except.pure] at hOk + | ok valueExpr => + simp [hExpr, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + /-- Each statement in the storageArrayPush fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_storageArrayPush_bridged @@ -7865,6 +11049,22 @@ theorem compileStmt_storageArrayPush_bridged dynamicSource internalRetNames isInternal inScopeNames field value f slot elemType hValue hFind hDynArr hOk +theorem compileStmt_storageArrayPush_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStorageArrayPushStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | storageArrayPush field value f slot elemType hValue hFind hDynArr => + exact compileStmt_storageArrayPush_singleSlot_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + value f slot elemType hFind hDynArr hOk + /-- Lists of `storageArrayPush` source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_storageArrayPush_bridged @@ -7910,6 +11110,22 @@ theorem compileStmtList_storageArrayPush_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_storageArrayPush_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStorageArrayPushStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceStorageArrayPushStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_storageArrayPush_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: `storageArrayPop` `Stmt.storageArrayPop field` compiles via `compileStorageArrayPop` to a @@ -8022,6 +11238,26 @@ theorem compileStmt_storageArrayPop_singleSlot_bridged (BridgedStraightStmt.expr_sstore_lit slot _ (BridgedExpr.ident "__array_new_len")) +private theorem compileStmt_storageArrayPop_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) (f : Field) (slot : Nat) + (elemType : StorageArrayElemType) + (hFind : findFieldWithResolvedSlot fields field = some (f, slot)) + (hDynArr : f.ty = .dynamicArray elemType) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.storageArrayPop field) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt] at hOk + unfold compileStorageArrayPop at hOk + unfold validateDynamicArrayField at hOk + simp [hFind, hDynArr, bind, Except.bind, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + /-- Each statement in the storageArrayPop fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_storageArrayPop_bridged @@ -8040,6 +11276,22 @@ theorem compileStmt_storageArrayPop_bridged dynamicSource internalRetNames isInternal inScopeNames field f slot elemType hFind hDynArr hOk +theorem compileStmt_storageArrayPop_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStorageArrayPopStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | storageArrayPop field f slot elemType hFind hDynArr => + exact compileStmt_storageArrayPop_singleSlot_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field f + slot elemType hFind hDynArr hOk + /-- Lists of `storageArrayPop` source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_storageArrayPop_bridged @@ -8085,6 +11337,22 @@ theorem compileStmtList_storageArrayPop_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_storageArrayPop_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStorageArrayPopStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceStorageArrayPopStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_storageArrayPop_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: `setStorageArrayElement` `Stmt.setStorageArrayElement field index value` compiles via @@ -8209,6 +11477,34 @@ theorem compileStmt_setStorageArrayElement_singleSlot_bridged (BridgedExpr.ident "__array_base") (BridgedExpr.ident "__array_index") hValBridged) +private theorem compileStmt_setStorageArrayElement_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) (index value : Expr) (f : Field) (slot : Nat) + (elemType : StorageArrayElemType) + (hFind : findFieldWithResolvedSlot fields field = some (f, slot)) + (hDynArr : f.ty = .dynamicArray elemType) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStorageArrayElement field index value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt] at hOk + unfold compileSetStorageArrayElement at hOk + unfold validateDynamicArrayField at hOk + simp [hFind, hDynArr, bind, Except.bind] at hOk + cases hIdxExpr : compileExpr fields dynamicSource index with + | error err => simp [hIdxExpr, Pure.pure, Except.pure] at hOk + | ok indexExpr => + simp [hIdxExpr, Pure.pure, Except.pure] at hOk + cases hValExpr : compileExpr fields dynamicSource value with + | error err => simp [hValExpr] at hOk + | ok valueExpr => + simp [hValExpr] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + /-- Each statement in the setStorageArrayElement fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_setStorageArrayElement_bridged @@ -8219,14 +11515,31 @@ theorem compileStmt_setStorageArrayElement_bridged ∀ {out : List YulStmt}, compileStmt fields events errors dynamicSource internalRetNames isInternal inScopeNames [] stmt = .ok out → - BridgedStmts out := by + BridgedStmts out := by + intro stmt hStmt out hOk + cases hStmt with + | setStorageArrayElement field index value f slot elemType + hIndex hValue hFind hDynArr => + exact compileStmt_setStorageArrayElement_singleSlot_bridged fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + index value f slot elemType hIndex hValue hFind hDynArr hOk + +theorem compileStmt_setStorageArrayElement_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceSetStorageArrayElementStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by intro stmt hStmt out hOk cases hStmt with | setStorageArrayElement field index value f slot elemType hIndex hValue hFind hDynArr => - exact compileStmt_setStorageArrayElement_singleSlot_bridged fields events - errors dynamicSource internalRetNames isInternal inScopeNames field - index value f slot elemType hIndex hValue hFind hDynArr hOk + exact compileStmt_setStorageArrayElement_singleSlot_noFuncDefs fields + events errors dynamicSource internalRetNames isInternal inScopeNames + field index value f slot elemType hFind hDynArr hOk /-- Lists of `setStorageArrayElement` source statements compile to Yul lists satisfying `BridgedStmts`. -/ @@ -8274,6 +11587,23 @@ theorem compileStmtList_setStorageArrayElement_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_setStorageArrayElement_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceSetStorageArrayElementStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal + (BridgedSourceSetStorageArrayElementStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_setStorageArrayElement_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: single-slot `setMappingWord` (wordOffset ≠ 0) @@ -8299,41 +11629,6 @@ inductive BridgedSourceMappingWordNonzeroStmt (fields : List Field) : Stmt → P def BridgedSourceMappingWordNonzeroStmts (fields : List Field) (stmts : List Stmt) : Prop := ∀ stmt ∈ stmts, BridgedSourceMappingWordNonzeroStmt fields stmt -/-- Shared helper: `compileMappingSlotWrite` on a single-slot mapping with -`wordOffset ≠ 0` and pre-compiled bridged key/value expressions produces a -`BridgedStmts` list (one `sstore(add(mappingSlot(lit slot, key), lit wordOffset), value)`). -/ -private theorem compileMappingSlotWrite_singleSlot_nonzero_bridged - (fields : List Field) (field : String) {slot wordOffset : Nat} - (keyExpr valueExpr : YulExpr) (label : String) - (hKey : BridgedExpr keyExpr) (hValue : BridgedExpr valueExpr) - (hMapping : isMapping fields field = true) - (hSlots : findFieldWriteSlots fields field = some [slot]) - (hNonzero : wordOffset ≠ 0) : - ∀ {out : List YulStmt}, - compileMappingSlotWrite fields field keyExpr valueExpr label wordOffset = .ok out → - BridgedStmts out := by - intro out hOk - have hBeq : (wordOffset == 0) = false := by - cases wordOffset with - | zero => exact absurd rfl hNonzero - | succ n => rfl - simp [compileMappingSlotWrite, hMapping, hSlots, hBeq, Pure.pure, Except.pure] at hOk - subst hOk - intro yulStmt hMem - simp only [List.mem_singleton] at hMem - subst yulStmt - have hMappingExpr : BridgedExpr (.call "mappingSlot" [.lit slot, keyExpr]) := by - refine BridgedExpr.call "mappingSlot" _ (Or.inl (by simp [bridgedBuiltins])) ?_ - intro arg hArg - simp only [List.mem_cons, List.not_mem_nil, or_false] at hArg - rcases hArg with rfl | rfl - · exact BridgedExpr.lit slot - · exact hKey - exact BridgedStmt.straight _ - (BridgedStraightStmt.expr_sstore_add - (.call "mappingSlot" [.lit slot, keyExpr]) (.lit wordOffset) valueExpr - hMappingExpr (BridgedExpr.lit wordOffset) hValue) - /-- A single-slot `Stmt.setMappingWord` source write at `wordOffset ≠ 0` with pure bridged key and value compiles to `BridgedStmts`. -/ theorem compileStmt_setMappingWord_singleSlot_nonzero_bridged @@ -8426,6 +11721,63 @@ theorem compileStmtList_mappingWordNonzero_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmt_setMappingWord_singleSlot_nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot wordOffset : Nat} {key value : Expr} + (_hKey : BridgedSourceExpr key) (_hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hNonzero : wordOffset ≠ 0) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMappingWord field key wordOffset value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr] at hOk + exact compileMappingSlotWrite_singleSlot_nonzero_noFuncDefs fields field + keyExpr valueExpr "setMappingWord" hMapping hSlots hNonzero hOk + +theorem compileStmt_mappingWordNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingWordNonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMappingWord field hKey hValue hMapping hSlots hNonzero => + exact compileStmt_setMappingWord_singleSlot_nonzero_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + hKey hValue hMapping hSlots hNonzero hOk + +theorem compileStmtList_mappingWordNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingWordNonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMappingWordNonzeroStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingWordNonzero_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: single-slot `setMapping2Word` (wordOffset ≠ 0) @@ -8585,6 +11937,73 @@ theorem compileStmtList_mapping2WordNonzero_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmt_setMapping2Word_singleSlot_nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot wordOffset : Nat} {key1 key2 value : Expr} + (_hKey1 : BridgedSourceExpr key1) (_hKey2 : BridgedSourceExpr key2) + (_hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hNonzero : wordOffset ≠ 0) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMapping2Word field key1 key2 wordOffset value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + have hBeq : (wordOffset == 0) = false := by + cases wordOffset with + | zero => exact absurd rfl hNonzero + | succ n => rfl + simp only [compileStmt] at hOk + unfold compileSetMapping2Word at hOk + simp [hMapping2, hSlots, hBeq] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst hOk + simp [Native.yulStmtContainsFuncDef] + +theorem compileStmt_mapping2WordNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMapping2WordNonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMapping2Word field hKey1 hKey2 hValue hMapping2 hSlots hNonzero => + exact compileStmt_setMapping2Word_singleSlot_nonzero_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + hKey1 hKey2 hValue hMapping2 hSlots hNonzero hOk + +theorem compileStmtList_mapping2WordNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMapping2WordNonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMapping2WordNonzeroStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mapping2WordNonzero_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: single-slot `setMappingChain` `Stmt.setMappingChain` dispatches through `compileSetMappingChain`. For a @@ -8703,6 +12122,31 @@ theorem compileStmt_setMappingChain_singleSlot_bridged (BridgedStraightStmt.expr_sstore_mapping _ last valueExpr hPreFold hLast hBridgedValue) +private theorem compileStmt_setMappingChain_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {keys : List Expr} {value : Expr} + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMappingChain field keys value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt] at hOk + unfold compileSetMappingChain at hOk + simp [hMapping, hSlots] at hOk + cases hKeyExprs : compileExprList fields dynamicSource keys with + | error err => simp [hKeyExprs, bind, Except.bind] at hOk + | ok keyExprs => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExprs, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKeyExprs, hValueExpr, bind, Except.bind] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + /-- Each statement in the mapping-chain-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mappingChain_bridged @@ -8721,6 +12165,22 @@ theorem compileStmt_mappingChain_bridged dynamicSource internalRetNames isInternal inScopeNames field hKeys hValue hMapping hSlots hOk +theorem compileStmt_mappingChain_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingChainStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMappingChain field hKeys hValue hMapping hSlots => + exact compileStmt_setMappingChain_singleSlot_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + hMapping hSlots hOk + /-- Lists of single-slot mapping-chain-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingChain_bridged @@ -8765,6 +12225,22 @@ theorem compileStmtList_mappingChain_bridged internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mappingChain_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingChainStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMappingChainStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingChain_noFuncDefs fields events errors dynamicSource + internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Multi-slot mapping-write source body closure (wordOffset = 0) Multi-slot `setMapping` / `setMappingUint` writes hit the compatibility branch @@ -8810,6 +12286,21 @@ private theorem bridgedStraightStmts_multiSlot_sstore_mapping (BridgedExpr.ident "__compat_value") · exact ih stmt hMem +private theorem yulStmtsContainFuncDef_multiSlot_sstore_mapping + (slots : List Nat) : + Native.yulStmtsContainFuncDef + (slots.map fun slot => + Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "sstore" [ + Compiler.Yul.YulExpr.call "mappingSlot" + [Compiler.Yul.YulExpr.lit slot, + Compiler.Yul.YulExpr.ident "__compat_key"], + Compiler.Yul.YulExpr.ident "__compat_value"])) = false := by + induction slots with + | nil => simp [Native.yulStmtsContainFuncDef] + | cons slot rest ih => + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef, ih] + /-- Shared helper: `compileMappingSlotWrite` on a multi-slot mapping (≥ 2 slots) with `wordOffset = 0` and pre-compiled bridged key/value expressions produces a `BridgedStmts` list (one outer block wrapping two let-bindings @@ -8867,6 +12358,22 @@ private theorem compileMappingSlotWrite_multiSlot_bridged (by simpa using hMem) exact BridgedStmt.straight _ hSstore +private theorem compileMappingSlotWrite_multiSlot_noFuncDefs + (fields : List Field) (field : String) + {slot0 slot1 : Nat} {slotsRest : List Nat} + (keyExpr valueExpr : YulExpr) (label : String) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) : + ∀ {out : List YulStmt}, + compileMappingSlotWrite fields field keyExpr valueExpr label 0 = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp [compileMappingSlotWrite, hMapping, hSlots, Pure.pure, Except.pure] at hOk + subst hOk + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef, + yulStmtsContainFuncDef_multiSlot_sstore_mapping] + /-- Multi-slot mapping-write source statements: `setMapping` / `setMappingUint` to a declared mapping field whose write slots list has ≥ 2 entries, with pure `BridgedSourceExpr` key/value. -/ @@ -8907,7 +12414,64 @@ theorem compileStmt_setMapping_multiSlot_bridged some (slot0 :: slot1 :: slotsRest)) : ∀ {out : List YulStmt}, compileStmt fields events errors dynamicSource internalRetNames isInternal - inScopeNames [] (.setMapping field key value) = .ok out → + inScopeNames [] (.setMapping field key value) = .ok out → + BridgedStmts out := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr] at hOk + exact compileMappingSlotWrite_multiSlot_bridged fields field keyExpr + valueExpr "setMapping" + (compileExpr_bridgedSource fields dynamicSource hKey hKeyExpr) + (compileExpr_bridgedSource fields dynamicSource hValue hValueExpr) + hMapping hSlots hOk + +theorem compileStmt_setMapping_multiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key value : Expr} + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMapping field key value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr] at hOk + exact compileMappingSlotWrite_multiSlot_noFuncDefs fields field + keyExpr valueExpr "setMapping" hMapping hSlots hOk + +/-- A multi-slot `Stmt.setMappingUint` source write with pure bridged key +and value compiles to `BridgedStmts`. Emission path is identical to +`Stmt.setMapping`, so this reuses the same mapping-write helper. -/ +theorem compileStmt_setMappingUint_multiSlot_bridged + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key value : Expr} + (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMappingUint field key value) = .ok out → BridgedStmts out := by intro out hOk simp only [compileStmt, bind, Except.bind] at hOk @@ -8919,28 +12483,24 @@ theorem compileStmt_setMapping_multiSlot_bridged | ok valueExpr => simp [hKeyExpr, hValueExpr] at hOk exact compileMappingSlotWrite_multiSlot_bridged fields field keyExpr - valueExpr "setMapping" + valueExpr "setMappingUint" (compileExpr_bridgedSource fields dynamicSource hKey hKeyExpr) (compileExpr_bridgedSource fields dynamicSource hValue hValueExpr) hMapping hSlots hOk -/-- A multi-slot `Stmt.setMappingUint` source write with pure bridged key -and value compiles to `BridgedStmts`. Emission path is identical to -`Stmt.setMapping`, so this reuses the same mapping-write helper. -/ -theorem compileStmt_setMappingUint_multiSlot_bridged +theorem compileStmt_setMappingUint_multiSlot_noFuncDefs (fields : List Field) (events : List EventDef) (errors : List ErrorDef) (dynamicSource : DynamicDataSource) (internalRetNames : List String) (isInternal : Bool) (inScopeNames : List String) (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} {key value : Expr} - (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) (hMapping : isMapping fields field = true) (hSlots : findFieldWriteSlots fields field = some (slot0 :: slot1 :: slotsRest)) : ∀ {out : List YulStmt}, compileStmt fields events errors dynamicSource internalRetNames isInternal inScopeNames [] (.setMappingUint field key value) = .ok out → - BridgedStmts out := by + Native.yulStmtsContainFuncDef out = false := by intro out hOk simp only [compileStmt, bind, Except.bind] at hOk cases hKeyExpr : compileExpr fields dynamicSource key with @@ -8950,11 +12510,8 @@ theorem compileStmt_setMappingUint_multiSlot_bridged | error err => simp [hKeyExpr, hValueExpr] at hOk | ok valueExpr => simp [hKeyExpr, hValueExpr] at hOk - exact compileMappingSlotWrite_multiSlot_bridged fields field keyExpr - valueExpr "setMappingUint" - (compileExpr_bridgedSource fields dynamicSource hKey hKeyExpr) - (compileExpr_bridgedSource fields dynamicSource hValue hValueExpr) - hMapping hSlots hOk + exact compileMappingSlotWrite_multiSlot_noFuncDefs fields field + keyExpr valueExpr "setMappingUint" hMapping hSlots hOk /-- Each statement in the multi-slot mapping-write fragment compiles to Yul satisfying `BridgedStmts`. -/ @@ -8978,6 +12535,26 @@ theorem compileStmt_mappingWriteMultiSlot_bridged dynamicSource internalRetNames isInternal inScopeNames field hKey hValue hMapping hSlots hOk +theorem compileStmt_mappingWriteMultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingWriteMultiSlotStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMapping field hKey hValue hMapping hSlots => + exact compileStmt_setMapping_multiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field + hMapping hSlots hOk + | setMappingUint field hKey hValue hMapping hSlots => + exact compileStmt_setMappingUint_multiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field + hMapping hSlots hOk + /-- Lists of multi-slot mapping-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingWriteMultiSlot_bridged @@ -9022,6 +12599,22 @@ theorem compileStmtList_mappingWriteMultiSlot_bridged dynamicSource internalRetNames isInternal inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mappingWriteMultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingWriteMultiSlotStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMappingWriteMultiSlotStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingWriteMultiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setMapping2` (wordOffset = 0) Multi-slot `setMapping2` writes hit the `_` arm of `compileSetMapping2`'s @@ -9085,6 +12678,23 @@ private theorem bridgedStraightStmts_multiSlot_sstore_mapping2 (BridgedExpr.ident "__compat_value") · exact ih stmt hMem +private theorem yulStmtsContainFuncDef_multiSlot_sstore_mapping2 + (slots : List Nat) : + Native.yulStmtsContainFuncDef + (slots.map fun slot => + Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "sstore" [ + Compiler.Yul.YulExpr.call "mappingSlot" + [Compiler.Yul.YulExpr.call "mappingSlot" + [Compiler.Yul.YulExpr.lit slot, + Compiler.Yul.YulExpr.ident "__compat_key1"], + Compiler.Yul.YulExpr.ident "__compat_key2"], + Compiler.Yul.YulExpr.ident "__compat_value"])) = false := by + induction slots with + | nil => simp [Native.yulStmtsContainFuncDef] + | cons slot rest ih => + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef, ih] + /-- Multi-slot double-mapping-write source statements: `setMapping2` to a declared `isMapping2` field whose write slots list has ≥ 2 entries, with pure `BridgedSourceExpr` key1/key2/value. -/ @@ -9202,6 +12812,38 @@ theorem compileStmt_setMapping2_multiSlot_bridged (by simpa using hMem) exact BridgedStmt.straight _ hSstore +theorem compileStmt_setMapping2_multiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key1 key2 value : Expr} + (hMapping2 : isMapping2 fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMapping2 field key1 key2 value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt] at hOk + unfold compileSetMapping2 at hOk + simp [hMapping2, hSlots] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef, + yulStmtsContainFuncDef_multiSlot_sstore_mapping2] + /-- Each statement in the multi-slot double-mapping-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mappingWrite2MultiSlot_bridged @@ -9220,6 +12862,22 @@ theorem compileStmt_mappingWrite2MultiSlot_bridged dynamicSource internalRetNames isInternal inScopeNames field hKey1 hKey2 hValue hMapping2 hSlots hOk +theorem compileStmt_mappingWrite2MultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingWrite2MultiSlotStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMapping2 field hKey1 hKey2 hValue hMapping2 hSlots => + exact compileStmt_setMapping2_multiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field + hMapping2 hSlots hOk + /-- Lists of multi-slot double-mapping-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingWrite2MultiSlot_bridged @@ -9267,6 +12925,22 @@ theorem compileStmtList_mappingWrite2MultiSlot_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mappingWrite2MultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingWrite2MultiSlotStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMappingWrite2MultiSlotStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingWrite2MultiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setStructMember` (wordOffset = 0) `Stmt.setStructMember` goes through `compileSetStructMember`. For an @@ -9338,6 +13012,40 @@ theorem compileStmt_setStructMember_multiSlot_bridged (compileExpr_bridgedSource fields dynamicSource hValue hValueExpr) hMapping hSlots hOk +theorem compileStmt_setStructMember_multiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key value : Expr} (memberName : String) + (members : List StructMember) (member : StructMember) + (hNotMapping2 : isMapping2 fields field = false) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hWordOffset : member.wordOffset = 0) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStructMember field key memberName value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, compileSetStructMember, hNotMapping2, hMembers, + hFindMember, hUnpacked, hWordOffset, bind, Except.bind, + Bool.false_eq_true, if_false] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr, pure, Pure.pure, Except.pure] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr, pure, Pure.pure, Except.pure] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr, pure, Pure.pure, Except.pure] at hOk + exact compileMappingSlotWrite_multiSlot_noFuncDefs fields field + keyExpr valueExpr s!"setStructMember.{memberName}" + hMapping hSlots hOk + /-- Each statement in the multi-slot struct-member-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_structMemberMultiSlot_bridged @@ -9358,6 +13066,24 @@ theorem compileStmt_structMemberMultiSlot_bridged members member hKey hValue hNotMapping2 hMembers hFindMember hUnpacked hWordOffset hMapping hSlots hOk +theorem compileStmt_structMemberMultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStructMemberMultiSlotStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setStructMember field memberName members member hKey hValue hNotMapping2 + hMembers hFindMember hUnpacked hWordOffset hMapping hSlots => + exact compileStmt_setStructMember_multiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames field memberName + members member hNotMapping2 hMembers hFindMember hUnpacked hWordOffset + hMapping hSlots hOk + /-- Lists of multi-slot struct-member-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_structMemberMultiSlot_bridged @@ -9405,6 +13131,22 @@ theorem compileStmtList_structMemberMultiSlot_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_structMemberMultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStructMemberMultiSlotStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceStructMemberMultiSlotStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_structMemberMultiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setStructMember2` (wordOffset = 0) @@ -9542,6 +13284,45 @@ theorem compileStmt_setStructMember2_multiSlot_bridged (by simpa using hMem) exact BridgedStmt.straight _ hSstore +theorem compileStmt_setStructMember2_multiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key1 key2 value : Expr} (memberName : String) + (members : List StructMember) (member : StructMember) + (hMapping2 : isMapping2 fields field = true) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hWordOffset : member.wordOffset = 0) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStructMember2 field key1 key2 memberName value) = + .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt] at hOk + unfold compileSetStructMember2 at hOk + simp [hMapping2, hMembers, hFindMember, hUnpacked, hWordOffset, hSlots] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + simpa [Function.comp_def] using + yulStmtsContainFuncDef_multiSlot_sstore_mapping2 slotsRest + /-- Each statement in the multi-slot struct-member2-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_structMember2MultiSlot_bridged @@ -9562,6 +13343,24 @@ theorem compileStmt_structMember2MultiSlot_bridged members member hKey1 hKey2 hValue hMapping2 hMembers hFindMember hUnpacked hWordOffset hSlots hOk +theorem compileStmt_structMember2MultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStructMember2MultiSlotStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setStructMember2 field memberName members member hKey1 hKey2 hValue hMapping2 + hMembers hFindMember hUnpacked hWordOffset hSlots => + exact compileStmt_setStructMember2_multiSlot_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + memberName members member hMapping2 hMembers hFindMember hUnpacked + hWordOffset hSlots hOk + /-- Lists of multi-slot struct-member2-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_structMember2MultiSlot_bridged @@ -9609,6 +13408,22 @@ theorem compileStmtList_structMember2MultiSlot_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_structMember2MultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStructMember2MultiSlotStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceStructMember2MultiSlotStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_structMember2MultiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setMappingWord` (wordOffset=0) @@ -9673,6 +13488,33 @@ theorem compileStmt_setMappingWord_multiSlot_bridged (compileExpr_bridgedSource fields dynamicSource hValue hValueExpr) hMapping hSlots hOk +theorem compileStmt_setMappingWord_multiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key value : Expr} (wordOffset : Nat) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) + (hWordOffset : wordOffset = 0) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMappingWord field key wordOffset value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + subst hWordOffset + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr] at hOk + exact compileMappingSlotWrite_multiSlot_noFuncDefs fields field + keyExpr valueExpr "setMappingWord" hMapping hSlots hOk + /-- Each statement in the multi-slot mappingWord-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mappingWordMultiSlot_bridged @@ -9691,6 +13533,22 @@ theorem compileStmt_mappingWordMultiSlot_bridged dynamicSource internalRetNames isInternal inScopeNames field wordOffset hKey hValue hMapping hSlots hWordOffset hOk +theorem compileStmt_mappingWordMultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingWordMultiSlotStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMappingWord field wordOffset hKey hValue hMapping hSlots hWordOffset => + exact compileStmt_setMappingWord_multiSlot_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + wordOffset hMapping hSlots hWordOffset hOk + /-- Lists of multi-slot mappingWord-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingWordMultiSlot_bridged @@ -9738,6 +13596,22 @@ theorem compileStmtList_mappingWordMultiSlot_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mappingWordMultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingWordMultiSlotStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMappingWordMultiSlotStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingWordMultiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setMapping2Word` (wordOffset=0) @@ -9866,6 +13740,41 @@ theorem compileStmt_setMapping2Word_multiSlot_bridged (by simpa using hMem) exact BridgedStmt.straight _ hSstore +theorem compileStmt_setMapping2Word_multiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key1 key2 value : Expr} (wordOffset : Nat) + (hMapping2 : isMapping2 fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) + (hWordOffset : wordOffset = 0) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMapping2Word field key1 key2 wordOffset value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + subst hWordOffset + simp only [compileStmt] at hOk + unfold compileSetMapping2Word at hOk + simp [hMapping2, hSlots] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + simpa [Function.comp_def] using + yulStmtsContainFuncDef_multiSlot_sstore_mapping2 slotsRest + /-- Each statement in the multi-slot mapping2Word-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mapping2WordMultiSlot_bridged @@ -9884,6 +13793,22 @@ theorem compileStmt_mapping2WordMultiSlot_bridged dynamicSource internalRetNames isInternal inScopeNames field wordOffset hKey1 hKey2 hValue hMapping2 hSlots hWordOffset hOk +theorem compileStmt_mapping2WordMultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMapping2WordMultiSlotStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMapping2Word field wordOffset hKey1 hKey2 hValue hMapping2 hSlots hWordOffset => + exact compileStmt_setMapping2Word_multiSlot_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + wordOffset hMapping2 hSlots hWordOffset hOk + /-- Lists of multi-slot mapping2Word-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mapping2WordMultiSlot_bridged @@ -9931,6 +13856,22 @@ theorem compileStmtList_mapping2WordMultiSlot_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mapping2WordMultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMapping2WordMultiSlotStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMapping2WordMultiSlotStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mapping2WordMultiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setMappingWord` (wordOffset ≠ 0) @@ -9992,6 +13933,23 @@ private theorem bridgedStraightStmts_multiSlot_sstore_mapping_add (BridgedExpr.ident "__compat_value") · exact ih stmt hMem +private theorem yulStmtsContainFuncDef_multiSlot_sstore_mapping_add + (slots : List Nat) (wordOffset : Nat) : + Native.yulStmtsContainFuncDef + (slots.map fun slot => + Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "sstore" [ + Compiler.Yul.YulExpr.call "add" [ + Compiler.Yul.YulExpr.call "mappingSlot" + [Compiler.Yul.YulExpr.lit slot, + Compiler.Yul.YulExpr.ident "__compat_key"], + Compiler.Yul.YulExpr.lit wordOffset], + Compiler.Yul.YulExpr.ident "__compat_value"])) = false := by + induction slots with + | nil => simp [Native.yulStmtsContainFuncDef] + | cons slot rest ih => + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef, ih] + /-- Shared helper: `compileMappingSlotWrite` on a multi-slot mapping (≥ 2 slots) with `wordOffset ≠ 0` and pre-compiled bridged key/value expressions produces a `BridgedStmts` list. Mirrors @@ -10030,6 +13988,29 @@ private theorem compileMappingSlotWrite_multiSlot_nonzero_bridged (slot0 :: slot1 :: slotsRest) wordOffset stmt (by simpa using hMem) exact BridgedStmt.straight _ hSstore +private theorem compileMappingSlotWrite_multiSlot_nonzero_noFuncDefs + (fields : List Field) (field : String) + {slot0 slot1 : Nat} {slotsRest : List Nat} {wordOffset : Nat} + (keyExpr valueExpr : YulExpr) (label : String) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) + (hNonzero : wordOffset ≠ 0) : + ∀ {out : List YulStmt}, + compileMappingSlotWrite fields field keyExpr valueExpr label wordOffset = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + have hBeq : (wordOffset == 0) = false := by + cases wordOffset with + | zero => exact absurd rfl hNonzero + | succ n => rfl + simp [compileMappingSlotWrite, hMapping, hSlots, hBeq, Pure.pure, + Except.pure] at hOk + subst hOk + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + simpa using + yulStmtsContainFuncDef_multiSlot_sstore_mapping_add slotsRest wordOffset + /-- A multi-slot `Stmt.setMappingWord field key wordOffset value` source write with pure bridged key and value at `wordOffset ≠ 0` on a mapping field whose write slots list has ≥ 2 entries. -/ @@ -10081,6 +14062,32 @@ theorem compileStmt_setMappingWord_multiSlot_nonzero_bridged (compileExpr_bridgedSource fields dynamicSource hValue hValueExpr) hMapping hSlots hNonzero hOk +theorem compileStmt_setMappingWord_multiSlot_nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key value : Expr} (wordOffset : Nat) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) + (hNonzero : wordOffset ≠ 0) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMappingWord field key wordOffset value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr] at hOk + exact compileMappingSlotWrite_multiSlot_nonzero_noFuncDefs fields field + keyExpr valueExpr "setMappingWord" hMapping hSlots hNonzero hOk + /-- Each statement in the multi-slot nonzero-offset mappingWord-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mappingWordMultiSlotNonzero_bridged @@ -10099,6 +14106,22 @@ theorem compileStmt_mappingWordMultiSlotNonzero_bridged dynamicSource internalRetNames isInternal inScopeNames field wordOffset hKey hValue hMapping hSlots hNonzero hOk +theorem compileStmt_mappingWordMultiSlotNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingWordMultiSlotNonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMappingWord field wordOffset hKey hValue hMapping hSlots hNonzero => + exact compileStmt_setMappingWord_multiSlot_nonzero_noFuncDefs fields + events errors dynamicSource internalRetNames isInternal inScopeNames + field wordOffset hMapping hSlots hNonzero hOk + /-- Lists of multi-slot nonzero-offset mappingWord-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingWordMultiSlotNonzero_bridged @@ -10146,6 +14169,23 @@ theorem compileStmtList_mappingWordMultiSlotNonzero_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mappingWordMultiSlotNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingWordMultiSlotNonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal + (BridgedSourceMappingWordMultiSlotNonzeroStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingWordMultiSlotNonzero_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setMapping2Word` (wordOffset ≠ 0) @@ -10228,6 +14268,25 @@ private theorem bridgedStraightStmts_multiSlot_sstore_mapping2_add (BridgedExpr.ident "__compat_value") · exact ih stmt hMem +private theorem yulStmtsContainFuncDef_multiSlot_sstore_mapping2_add + (slots : List Nat) (wordOffset : Nat) : + Native.yulStmtsContainFuncDef + (slots.map fun slot => + Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "sstore" [ + Compiler.Yul.YulExpr.call "add" [ + Compiler.Yul.YulExpr.call "mappingSlot" [ + Compiler.Yul.YulExpr.call "mappingSlot" + [Compiler.Yul.YulExpr.lit slot, + Compiler.Yul.YulExpr.ident "__compat_key1"], + Compiler.Yul.YulExpr.ident "__compat_key2"], + Compiler.Yul.YulExpr.lit wordOffset], + Compiler.Yul.YulExpr.ident "__compat_value"])) = false := by + induction slots with + | nil => simp [Native.yulStmtsContainFuncDef] + | cons slot rest ih => + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef, ih] + /-- A multi-slot `Stmt.setMapping2Word field key1 key2 wordOffset value` source write with pure bridged key1/key2/value at `wordOffset ≠ 0` on a declared `isMapping2` field whose write slots list has ≥ 2 entries. -/ @@ -10374,6 +14433,45 @@ theorem compileStmt_setMapping2Word_multiSlot_nonzero_bridged wordOffset stmt (by simpa using hMem) exact BridgedStmt.straight _ hSstore +theorem compileStmt_setMapping2Word_multiSlot_nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key1 key2 value : Expr} {wordOffset : Nat} + (hMapping2 : isMapping2 fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) + (hNonzero : wordOffset ≠ 0) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setMapping2Word field key1 key2 wordOffset value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + have hBeq : (wordOffset == 0) = false := by + cases wordOffset with + | zero => exact absurd rfl hNonzero + | succ n => rfl + simp only [compileStmt] at hOk + unfold compileSetMapping2Word at hOk + simp [hMapping2, hSlots, hBeq] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + simpa [Function.comp_def] using + yulStmtsContainFuncDef_multiSlot_sstore_mapping2_add slotsRest + wordOffset + /-- Each statement in the multi-slot mapping2Word-write wordOffset≠0 fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mapping2WordMultiSlotNonzero_bridged @@ -10392,6 +14490,22 @@ theorem compileStmt_mapping2WordMultiSlotNonzero_bridged dynamicSource internalRetNames isInternal inScopeNames field hKey1 hKey2 hValue hMapping2 hSlots hNonzero hOk +theorem compileStmt_mapping2WordMultiSlotNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMapping2WordMultiSlotNonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMapping2Word field hKey1 hKey2 hValue hMapping2 hSlots hNonzero => + exact compileStmt_setMapping2Word_multiSlot_nonzero_noFuncDefs fields + events errors dynamicSource internalRetNames isInternal inScopeNames + field hMapping2 hSlots hNonzero hOk + /-- Lists of multi-slot mapping2Word-write wordOffset≠0 source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mapping2WordMultiSlotNonzero_bridged @@ -10439,6 +14553,23 @@ theorem compileStmtList_mapping2WordMultiSlotNonzero_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mapping2WordMultiSlotNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMapping2WordMultiSlotNonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal + (BridgedSourceMapping2WordMultiSlotNonzeroStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mapping2WordMultiSlotNonzero_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setStructMember` (wordOffset ≠ 0) @@ -10513,6 +14644,41 @@ theorem compileStmt_setStructMember_multiSlot_nonzero_bridged (compileExpr_bridgedSource fields dynamicSource hValue hValueExpr) hMapping hSlots hNonzero hOk +theorem compileStmt_setStructMember_multiSlot_nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key value : Expr} (memberName : String) + (members : List StructMember) (member : StructMember) + (hNotMapping2 : isMapping2 fields field = false) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hNonzero : member.wordOffset ≠ 0) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStructMember field key memberName value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + simp only [compileStmt, compileSetStructMember, hNotMapping2, hMembers, + hFindMember, hUnpacked, bind, Except.bind, + Bool.false_eq_true, if_false] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr, pure, Pure.pure, Except.pure] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => + simp [hKeyExpr, hValueExpr, pure, Pure.pure, Except.pure] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr, pure, Pure.pure, Except.pure] at hOk + exact compileMappingSlotWrite_multiSlot_nonzero_noFuncDefs fields + field keyExpr valueExpr s!"setStructMember.{memberName}" + hMapping hSlots hNonzero hOk + /-- Each statement in the multi-slot nonzero-offset struct-member-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_structMemberMultiSlotNonzero_bridged @@ -10533,6 +14699,24 @@ theorem compileStmt_structMemberMultiSlotNonzero_bridged memberName members member hKey hValue hNotMapping2 hMembers hFindMember hUnpacked hNonzero hMapping hSlots hOk +theorem compileStmt_structMemberMultiSlotNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStructMemberMultiSlotNonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setStructMember field memberName members member hKey hValue hNotMapping2 + hMembers hFindMember hUnpacked hNonzero hMapping hSlots => + exact compileStmt_setStructMember_multiSlot_nonzero_noFuncDefs fields + events errors dynamicSource internalRetNames isInternal inScopeNames field + memberName members member hNotMapping2 hMembers hFindMember hUnpacked + hNonzero hMapping hSlots hOk + /-- Lists of multi-slot nonzero-offset struct-member-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_structMemberMultiSlotNonzero_bridged @@ -10580,6 +14764,23 @@ theorem compileStmtList_structMemberMultiSlotNonzero_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_structMemberMultiSlotNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStructMemberMultiSlotNonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal + (BridgedSourceStructMemberMultiSlotNonzeroStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_structMemberMultiSlotNonzero_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setStructMember2` (wordOffset ≠ 0) @@ -10749,6 +14950,50 @@ theorem compileStmt_setStructMember2_multiSlot_nonzero_bridged member.wordOffset stmt (by simpa using hMem) exact BridgedStmt.straight _ hSstore +theorem compileStmt_setStructMember2_multiSlot_nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key1 key2 value : Expr} (memberName : String) + (members : List StructMember) (member : StructMember) + (hMapping2 : isMapping2 fields field = true) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hNonzero : member.wordOffset ≠ 0) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] (.setStructMember2 field key1 key2 memberName value) = + .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + have hBeq : (member.wordOffset == 0) = false := by + cases h : member.wordOffset with + | zero => exact absurd h hNonzero + | succ n => rfl + simp only [compileStmt] at hOk + unfold compileSetStructMember2 at hOk + simp [hMapping2, hMembers, hFindMember, hUnpacked, hBeq, hSlots] at hOk + cases hKey1Expr : compileExpr fields dynamicSource key1 with + | error err => simp [hKey1Expr, bind, Except.bind] at hOk + | ok key1Expr => + cases hKey2Expr : compileExpr fields dynamicSource key2 with + | error err => simp [hKey1Expr, hKey2Expr, bind, Except.bind] at hOk + | ok key2Expr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + | ok valueExpr => + simp [hKey1Expr, hKey2Expr, hValueExpr, bind, Except.bind] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + simpa [Function.comp_def] using + yulStmtsContainFuncDef_multiSlot_sstore_mapping2_add slotsRest + member.wordOffset + /-- Each statement in the multi-slot nonzero-offset struct-member2-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_structMember2MultiSlotNonzero_bridged @@ -10769,6 +15014,24 @@ theorem compileStmt_structMember2MultiSlotNonzero_bridged memberName members member hKey1 hKey2 hValue hMapping2 hMembers hFindMember hUnpacked hNonzero hSlots hOk +theorem compileStmt_structMember2MultiSlotNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceStructMember2MultiSlotNonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setStructMember2 field memberName members member hKey1 hKey2 hValue hMapping2 + hMembers hFindMember hUnpacked hNonzero hSlots => + exact compileStmt_setStructMember2_multiSlot_nonzero_noFuncDefs fields + events errors dynamicSource internalRetNames isInternal inScopeNames field + memberName members member hMapping2 hMembers hFindMember hUnpacked + hNonzero hSlots hOk + /-- Lists of multi-slot nonzero-offset struct-member2-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_structMember2MultiSlotNonzero_bridged @@ -10816,6 +15079,23 @@ theorem compileStmtList_structMember2MultiSlotNonzero_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_structMember2MultiSlotNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceStructMember2MultiSlotNonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal + (BridgedSourceStructMember2MultiSlotNonzeroStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_structMember2MultiSlotNonzero_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: single-slot `setMappingPackedWord` (wordOffset=0) @@ -10965,6 +15245,35 @@ theorem compileStmt_setMappingPackedWord_singleSlot_bridged (Compiler.Yul.YulExpr.lit slot) keyExpr _ (BridgedExpr.lit slot) hKeyBridged hVal) +theorem compileStmt_setMappingPackedWord_singleSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot : Nat} {key value : Expr} + (wordOffset : Nat) (packed : PackedBits) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hWordOffset : wordOffset = 0) + (hPacked : packedBitsValid packed = true) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames + [] (.setMappingPackedWord field key wordOffset packed value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + subst hWordOffset + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr, compileMappingPackedSlotWrite, + hMapping, hPacked, hSlots, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + /-- Each statement in the mappingPackedWord-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mappingPackedWord_bridged @@ -10984,6 +15293,23 @@ theorem compileStmt_mappingPackedWord_bridged errors dynamicSource internalRetNames isInternal inScopeNames field wordOffset packed hKey hValue hMapping hSlots hWordOffset hPacked hOk +theorem compileStmt_mappingPackedWord_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingPackedWordStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMappingPackedWord field wordOffset packed hKey hValue hMapping hSlots + hWordOffset hPacked => + exact compileStmt_setMappingPackedWord_singleSlot_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + wordOffset packed hMapping hSlots hWordOffset hPacked hOk + /-- Lists of single-slot mappingPackedWord-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingPackedWord_bridged @@ -11030,6 +15356,22 @@ theorem compileStmtList_mappingPackedWord_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mappingPackedWord_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingPackedWordStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal (BridgedSourceMappingPackedWordStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingPackedWord_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: single-slot `setMappingPackedWord` (wordOffset ≠ 0) @@ -11193,6 +15535,38 @@ theorem compileStmt_setMappingPackedWord_singleSlot_nonzero_bridged (Compiler.Yul.YulExpr.lit wordOffset) _ hMappingBase (BridgedExpr.lit wordOffset) hVal) +theorem compileStmt_setMappingPackedWord_singleSlot_nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot wordOffset : Nat} {key value : Expr} + (packed : PackedBits) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hNonzero : wordOffset ≠ 0) + (hPacked : packedBitsValid packed = true) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames + [] (.setMappingPackedWord field key wordOffset packed value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + have hBeq : (wordOffset == 0) = false := by + cases wordOffset with + | zero => exact absurd rfl hNonzero + | succ n => rfl + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr, compileMappingPackedSlotWrite, + hMapping, hPacked, hSlots, hBeq, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + /-- Each statement in the wordOffset≠0 mappingPackedWord-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mappingPackedWordNonzero_bridged @@ -11212,6 +15586,23 @@ theorem compileStmt_mappingPackedWordNonzero_bridged events errors dynamicSource internalRetNames isInternal inScopeNames field packed hKey hValue hMapping hSlots hNonzero hPacked hOk +theorem compileStmt_mappingPackedWordNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, BridgedSourceMappingPackedWordNonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMappingPackedWord field packed hKey hValue hMapping hSlots hNonzero + hPacked => + exact compileStmt_setMappingPackedWord_singleSlot_nonzero_noFuncDefs + fields events errors dynamicSource internalRetNames isInternal + inScopeNames field packed hMapping hSlots hNonzero hPacked hOk + /-- Lists of single-slot wordOffset≠0 mappingPackedWord-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingPackedWordNonzero_bridged @@ -11259,6 +15650,23 @@ theorem compileStmtList_mappingPackedWordNonzero_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mappingPackedWordNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingPackedWordNonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal + (BridgedSourceMappingPackedWordNonzeroStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingPackedWordNonzero_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setMappingPackedWord` (wordOffset = 0) @@ -11401,6 +15809,35 @@ private theorem bridgedStmts_slotsMap_packedInnerBlock_wordOffsetZero subst hEq exact bridgedStmt_packedInnerBlock_wordOffsetZero slot packed +private theorem yulStmtsContainFuncDef_slotsMap_packedInnerBlock_wordOffsetZero + (slots : List Nat) (packed : PackedBits) : + Native.yulStmtsContainFuncDef (slots.map (fun slot => + Compiler.Yul.YulStmt.block [ + Compiler.Yul.YulStmt.let_ "__compat_slot_word" + (Compiler.Yul.YulExpr.call "sload" [ + Compiler.Yul.YulExpr.call "mappingSlot" [ + Compiler.Yul.YulExpr.lit slot, + Compiler.Yul.YulExpr.ident "__compat_key"]]), + Compiler.Yul.YulStmt.let_ "__compat_slot_cleared" + (Compiler.Yul.YulExpr.call "and" [ + Compiler.Yul.YulExpr.ident "__compat_slot_word", + Compiler.Yul.YulExpr.call "not" [ + Compiler.Yul.YulExpr.lit (packedShiftedMaskNat packed)]]), + Compiler.Yul.YulStmt.expr ( + Compiler.Yul.YulExpr.call "sstore" [ + Compiler.Yul.YulExpr.call "mappingSlot" [ + Compiler.Yul.YulExpr.lit slot, + Compiler.Yul.YulExpr.ident "__compat_key"], + Compiler.Yul.YulExpr.call "or" [ + Compiler.Yul.YulExpr.ident "__compat_slot_cleared", + Compiler.Yul.YulExpr.call "shl" [ + Compiler.Yul.YulExpr.lit packed.offset, + Compiler.Yul.YulExpr.ident "__compat_packed"]]])])) = false := by + induction slots with + | nil => simp [Native.yulStmtsContainFuncDef] + | cons slot rest ih => + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef, ih] + /-- A multi-slot `Stmt.setMappingPackedWord field key 0 packed value` source write with pure bridged key and value, on a declared `isMapping` field whose write slots list has ≥ 2 entries. -/ @@ -11490,6 +15927,39 @@ theorem compileStmt_setMappingPackedWord_multiSlot_bridged · exact bridgedStmts_slotsMap_packedInnerBlock_wordOffsetZero slotsRest packed stmt hMem +theorem compileStmt_setMappingPackedWord_multiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key value : Expr} (wordOffset : Nat) (packed : PackedBits) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) + (hWordOffset : wordOffset = 0) + (hPacked : packedBitsValid packed = true) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames + [] (.setMappingPackedWord field key wordOffset packed value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + subst hWordOffset + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr, compileMappingPackedSlotWrite, + hMapping, hPacked, hSlots, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + simpa using + yulStmtsContainFuncDef_slotsMap_packedInnerBlock_wordOffsetZero + slotsRest packed + /-- Each statement in the multi-slot mappingPackedWord-write fragment (wordOffset=0) compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mappingPackedWordMultiSlot_bridged @@ -11510,6 +15980,24 @@ theorem compileStmt_mappingPackedWordMultiSlot_bridged errors dynamicSource internalRetNames isInternal inScopeNames field wordOffset packed hKey hValue hMapping hSlots hWordOffset hPacked hOk +theorem compileStmt_mappingPackedWordMultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceMappingPackedWordMultiSlotStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMappingPackedWord field wordOffset packed hKey hValue hMapping hSlots + hWordOffset hPacked => + exact compileStmt_setMappingPackedWord_multiSlot_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames field + wordOffset packed hMapping hSlots hWordOffset hPacked hOk + /-- Lists of multi-slot mappingPackedWord-write source statements (wordOffset=0) compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingPackedWordMultiSlot_bridged @@ -11557,6 +16045,23 @@ theorem compileStmtList_mappingPackedWordMultiSlot_bridged hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mappingPackedWordMultiSlot_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingPackedWordMultiSlotStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal + (BridgedSourceMappingPackedWordMultiSlotStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingPackedWordMultiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Source statement body closure: multi-slot `setMappingPackedWord` (wordOffset ≠ 0) @@ -11717,6 +16222,39 @@ private theorem bridgedStmts_slotsMap_packedInnerBlock_wordOffsetNonzero subst hEq exact bridgedStmt_packedInnerBlock_wordOffsetNonzero slot wordOffset packed +private theorem yulStmtsContainFuncDef_slotsMap_packedInnerBlock_wordOffsetNonzero + (slots : List Nat) (wordOffset : Nat) (packed : PackedBits) : + Native.yulStmtsContainFuncDef (slots.map (fun slot => + Compiler.Yul.YulStmt.block [ + Compiler.Yul.YulStmt.let_ "__compat_slot_word" + (Compiler.Yul.YulExpr.call "sload" [ + Compiler.Yul.YulExpr.call "add" [ + Compiler.Yul.YulExpr.call "mappingSlot" [ + Compiler.Yul.YulExpr.lit slot, + Compiler.Yul.YulExpr.ident "__compat_key"], + Compiler.Yul.YulExpr.lit wordOffset]]), + Compiler.Yul.YulStmt.let_ "__compat_slot_cleared" + (Compiler.Yul.YulExpr.call "and" [ + Compiler.Yul.YulExpr.ident "__compat_slot_word", + Compiler.Yul.YulExpr.call "not" [ + Compiler.Yul.YulExpr.lit (packedShiftedMaskNat packed)]]), + Compiler.Yul.YulStmt.expr ( + Compiler.Yul.YulExpr.call "sstore" [ + Compiler.Yul.YulExpr.call "add" [ + Compiler.Yul.YulExpr.call "mappingSlot" [ + Compiler.Yul.YulExpr.lit slot, + Compiler.Yul.YulExpr.ident "__compat_key"], + Compiler.Yul.YulExpr.lit wordOffset], + Compiler.Yul.YulExpr.call "or" [ + Compiler.Yul.YulExpr.ident "__compat_slot_cleared", + Compiler.Yul.YulExpr.call "shl" [ + Compiler.Yul.YulExpr.lit packed.offset, + Compiler.Yul.YulExpr.ident "__compat_packed"]]])])) = false := by + induction slots with + | nil => simp [Native.yulStmtsContainFuncDef] + | cons slot rest ih => + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef, ih] + /-- A multi-slot `Stmt.setMappingPackedWord field key wordOffset packed value` source write with pure bridged key and value at `wordOffset ≠ 0`, on a declared `isMapping` field whose write slots list has ≥ 2 entries. -/ @@ -11809,6 +16347,42 @@ theorem compileStmt_setMappingPackedWord_multiSlot_nonzero_bridged · exact bridgedStmts_slotsMap_packedInnerBlock_wordOffsetNonzero slotsRest wordOffset packed stmt hMem +theorem compileStmt_setMappingPackedWord_multiSlot_nonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) + (field : String) {slot0 slot1 : Nat} {slotsRest : List Nat} + {key value : Expr} {wordOffset : Nat} (packed : PackedBits) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = + some (slot0 :: slot1 :: slotsRest)) + (hNonzero : wordOffset ≠ 0) + (hPacked : packedBitsValid packed = true) : + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames isInternal + inScopeNames + [] (.setMappingPackedWord field key wordOffset packed value) = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro out hOk + have hBeq : (wordOffset == 0) = false := by + cases wordOffset with + | zero => exact absurd rfl hNonzero + | succ n => rfl + simp only [compileStmt, bind, Except.bind] at hOk + cases hKeyExpr : compileExpr fields dynamicSource key with + | error err => simp [hKeyExpr] at hOk + | ok keyExpr => + cases hValueExpr : compileExpr fields dynamicSource value with + | error err => simp [hKeyExpr, hValueExpr] at hOk + | ok valueExpr => + simp [hKeyExpr, hValueExpr, compileMappingPackedSlotWrite, + hMapping, hPacked, hSlots, hBeq, Pure.pure, Except.pure] at hOk + subst out + simp [Native.yulStmtContainsFuncDef, Native.yulStmtsContainFuncDef] + simpa using + yulStmtsContainFuncDef_slotsMap_packedInnerBlock_wordOffsetNonzero + slotsRest wordOffset packed + /-- Each statement in the multi-slot wordOffset≠0 mappingPackedWord-write fragment compiles to Yul satisfying `BridgedStmts`. -/ theorem compileStmt_mappingPackedWordMultiSlotNonzero_bridged @@ -11829,6 +16403,24 @@ theorem compileStmt_mappingPackedWordMultiSlotNonzero_bridged events errors dynamicSource internalRetNames isInternal inScopeNames field packed hKey hValue hMapping hSlots hNonzero hPacked hOk +theorem compileStmt_mappingPackedWordMultiSlotNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) : + ∀ {stmt : Stmt}, + BridgedSourceMappingPackedWordMultiSlotNonzeroStmt fields stmt → + ∀ {out : List YulStmt}, + compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmt = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmt hStmt out hOk + cases hStmt with + | setMappingPackedWord field packed hKey hValue hMapping hSlots hNonzero + hPacked => + exact compileStmt_setMappingPackedWord_multiSlot_nonzero_noFuncDefs fields + events errors dynamicSource internalRetNames isInternal inScopeNames + field packed hMapping hSlots hNonzero hPacked hOk + /-- Lists of multi-slot wordOffset≠0 mappingPackedWord-write source statements compile to Yul lists satisfying `BridgedStmts`. -/ theorem compileStmtList_mappingPackedWordMultiSlotNonzero_bridged @@ -11878,6 +16470,23 @@ theorem compileStmtList_mappingPackedWordMultiSlotNonzero_bridged inScopeNames hHeadSource hHead) (ih (collectStmtNames head ++ inScopeNames) hTailSource hTail) +theorem compileStmtList_mappingPackedWordMultiSlotNonzero_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSourceMappingPackedWordMultiSlotNonzeroStmts fields stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := + compileStmtList_noFuncDefs_of_forall fields events errors dynamicSource + internalRetNames isInternal + (BridgedSourceMappingPackedWordMultiSlotNonzeroStmt fields) + (fun inScopeNames {_} {_} hStmt hOk => + compileStmt_mappingPackedWordMultiSlotNonzero_noFuncDefs fields events + errors dynamicSource internalRetNames isInternal inScopeNames hStmt hOk) + /-! ## Universal safe-body closure @@ -11901,24 +16510,63 @@ inductive BridgedSafeStmts (hStmts : BridgedSourceInternalRecursiveBodyWithRawLogStmts fields errors dynamicSource stmts) : BridgedSafeStmts fields errors dynamicSource internalRetNames true stmts + | storage {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceStorageStmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | storageAddr {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceStorageAddrStmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | require {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceRequireStmts fields dynamicSource stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts | setStorageArrayElement {isInternal : Bool} {stmts : List Stmt} (hStmts : BridgedSourceSetStorageArrayElementStmts fields stmts) : BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts | mappingChain {isInternal : Bool} {stmts : List Stmt} (hStmts : BridgedSourceMappingChainStmts fields stmts) : BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | mappingWrite {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceMappingWriteStmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts | mappingWriteMultiSlot {isInternal : Bool} {stmts : List Stmt} (hStmts : BridgedSourceMappingWriteMultiSlotStmts fields stmts) : BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | mappingWrite2 {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceMappingWrite2Stmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts | mappingWrite2MultiSlot {isInternal : Bool} {stmts : List Stmt} (hStmts : BridgedSourceMappingWrite2MultiSlotStmts fields stmts) : BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | structMember {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceStructMemberStmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | structMember2 {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceStructMember2Stmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | structMemberNonzero {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceStructMemberNonzeroStmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | structMember2Nonzero {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceStructMember2NonzeroStmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts | structMemberMultiSlot {isInternal : Bool} {stmts : List Stmt} (hStmts : BridgedSourceStructMemberMultiSlotStmts fields stmts) : BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts | structMember2MultiSlot {isInternal : Bool} {stmts : List Stmt} (hStmts : BridgedSourceStructMember2MultiSlotStmts fields stmts) : BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | mappingWord {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceMappingWordStmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | mapping2Word {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceMapping2WordStmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | mappingWordNonzero {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceMappingWordNonzeroStmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | mapping2WordNonzero {isInternal : Bool} {stmts : List Stmt} + (hStmts : BridgedSourceMapping2WordNonzeroStmts fields stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts | mappingWordMultiSlot {isInternal : Bool} {stmts : List Stmt} (hStmts : BridgedSourceMappingWordMultiSlotStmts fields stmts) : BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts @@ -11967,6 +16615,745 @@ inductive BridgedSafeStmts | storageArrayPop {isInternal : Bool} {stmts : List Stmt} (hStmts : BridgedSourceStorageArrayPopStmts fields stmts) : BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal stmts + | append {isInternal : Bool} {pfx sfx : List Stmt} + (hPfx : BridgedSafeStmts fields errors dynamicSource internalRetNames + isInternal pfx) + (hSfx : BridgedSafeStmts fields errors dynamicSource internalRetNames + isInternal sfx) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + (pfx ++ sfx) + +private theorem compileStmtList_append_eq + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) (inScopeNames : List String) (adtTypes : List AdtTypeDef) + (pfx sfx : List Stmt) : + compileStmtList fields events errors dynamicSource internalRetNames isInternal + inScopeNames adtTypes (pfx ++ sfx) = + match + compileStmtList fields events errors dynamicSource internalRetNames isInternal + inScopeNames adtTypes pfx + with + | .error err => .error err + | .ok pfxOut => + match + compileStmtList fields events errors dynamicSource internalRetNames + isInternal + (List.foldl (fun scope stmt => collectStmtNames stmt ++ scope) + inScopeNames pfx) + adtTypes sfx + with + | .error err => .error err + | .ok sfxOut => .ok (pfxOut ++ sfxOut) := by + induction pfx generalizing inScopeNames with + | nil => + simp [compileStmtList, Pure.pure, Except.pure] + cases compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames adtTypes sfx <;> rfl + | cons head tail ih => + simp only [List.cons_append, compileStmtList, bind, Except.bind] + cases hHead : compileStmt fields events errors dynamicSource internalRetNames + isInternal inScopeNames adtTypes head with + | error err => + simp [hHead] + | ok headOut => + simp [hHead] + rw [ih (collectStmtNames head ++ inScopeNames)] + cases hTail : compileStmtList fields events errors dynamicSource + internalRetNames isInternal (collectStmtNames head ++ inScopeNames) + adtTypes tail with + | error err => + simp [hTail] + | ok tailOut => + simp [hTail] + cases hSfx : compileStmtList fields events errors dynamicSource + internalRetNames isInternal + ((List.map collectStmtNames tail).reverse.flatten ++ + (collectStmtNames head ++ inScopeNames)) + adtTypes sfx with + | error err => + simp [hSfx, Pure.pure, Except.pure] + | ok sfxOut => + simp [hSfx, List.append_assoc, Pure.pure, Except.pure] + +/-- The singleton `mstore` shape exposed by `SupportedFragment.mstoreSingle` + is a native safe body whenever its offset and value are compile-core + expressions. -/ +theorem bridgedSafeStmts_mstoreSingle_of_exprCompileCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {offset value : Expr} + (hOffset : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hValue : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.mstore offset value] := + BridgedSafeStmts.mstore (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact bridgedSourceMstoreStmt_of_exprCompileCore hOffset hValue) + +/-- The singleton `setStorage` shape exposed by + `SupportedFragment.setStorageSingleSlot` is a native safe body whenever its + value is a compile-core expression and the field is an unpacked uint slot. -/ +theorem bridgedSafeStmts_setStorageSingleSlot_of_exprCompileCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {fieldName : String} {value : Expr} {slot : Nat} + (hValue : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) + (hFind : + findFieldWithResolvedSlot fields fieldName = + some ({ name := fieldName, ty := FieldType.uint256 }, slot)) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setStorage fieldName value] := + BridgedSafeStmts.storage (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact bridgedSourceStorageStmt_setStorageSingleSlot_of_exprCompileCore + hValue hFind) + +/-- The singleton `setStorageAddr` shape exposed by + `SupportedFragment.setStorageAddrSingleSlot` is a native safe body whenever + its value is a compile-core expression and the field is an unpacked address + slot. -/ +theorem bridgedSafeStmts_setStorageAddrSingleSlot_of_exprCompileCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {fieldName : String} {value : Expr} {slot : Nat} + (hValue : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) + (hFind : + findFieldWithResolvedSlot fields fieldName = + some ({ name := fieldName, ty := FieldType.address }, slot)) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setStorageAddr fieldName value] := + BridgedSafeStmts.storageAddr (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact bridgedSourceStorageAddrStmt_setStorageAddrSingleSlot_of_exprCompileCore + hValue hFind) + +/-- A singleton `require` whose condition is compile-core is a native safe + body. -/ +theorem bridgedSafeStmts_requireSingle_of_exprCompileCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {cond : Expr} {message : String} + (hCond : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore cond) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.require cond message] := + BridgedSafeStmts.require (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact bridgedSourceRequireStmt_of_exprCompileCore hCond) + +/-- A singleton literal guard-family clause is a native safe body. -/ +theorem bridgedSafeStmts_requireGuardFamilyClause + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} + (clause : RequireLiteralGuardFamilyClause) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [clause.toStmt] := + BridgedSafeStmts.require (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact bridgedSourceRequireStmt_of_guardFamilyClause clause) + +/-- A `let` binding whose RHS is syntactic `keccak256(offset, size)` is a + native pure-binding source statement when the offset and size arguments are + compile-core expressions. This deliberately stays outside + `StmtListCompileCore`, whose source/IR semantic theorem still excludes + memory-slice hashing. -/ +theorem bridgedSourcePureBindingStmt_letKeccak_of_exprCompileCore + {name : String} {offset size : Expr} + (hOffset : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hSize : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore size) : + BridgedSourcePureBindingStmt + (.letVar name (.keccak256 offset size)) := + BridgedSourcePureBindingStmt.letVar name (.keccak256 offset size) + (bridgedSourceExpr_keccak256_of_exprCompileCore hOffset hSize) + +/-- An assignment whose RHS is syntactic `keccak256(offset, size)` is a native + pure-binding source statement when the offset and size arguments are + compile-core expressions. -/ +theorem bridgedSourcePureBindingStmt_assignKeccak_of_exprCompileCore + {name : String} {offset size : Expr} + (hOffset : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hSize : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore size) : + BridgedSourcePureBindingStmt + (.assignVar name (.keccak256 offset size)) := + BridgedSourcePureBindingStmt.assignVar name (.keccak256 offset size) + (bridgedSourceExpr_keccak256_of_exprCompileCore hOffset hSize) + +/-- Singleton native safe-body package for `let name := keccak256(offset,size)` + with compile-core offset and size arguments. -/ +theorem bridgedSafeStmts_letKeccak_of_exprCompileCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {name : String} {offset size : Expr} + (hOffset : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hSize : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore size) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.letVar name (.keccak256 offset size)] := + BridgedSafeStmts.storage (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceStorageStmt.pureBinding + (bridgedSourcePureBindingStmt_letKeccak_of_exprCompileCore hOffset hSize)) + +/-- Singleton native safe-body package for `name := keccak256(offset,size)` + with compile-core offset and size arguments. -/ +theorem bridgedSafeStmts_assignKeccak_of_exprCompileCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {name : String} {offset size : Expr} + (hOffset : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hSize : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore size) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.assignVar name (.keccak256 offset size)] := + BridgedSafeStmts.storage (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceStorageStmt.pureBinding + (bridgedSourcePureBindingStmt_assignKeccak_of_exprCompileCore hOffset hSize)) + +private def bridgedExternalRawLogLetVar + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {name : String} {value : Expr} + (hValue : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) : + BridgedSourceExternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource (.letVar name value) := + .base (.base (.base (.storage (.pureBinding + (.letVar _ _ (bridgedSourceExpr_of_exprCompileCore hValue)))))) + +private def bridgedExternalRawLogLetKeccak + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {name : String} {offset size : Expr} + (hOffset : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hSize : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore size) : + BridgedSourceExternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource (.letVar name (.keccak256 offset size)) := + .base (.base (.base (.storage (.pureBinding + (bridgedSourcePureBindingStmt_letKeccak_of_exprCompileCore hOffset hSize))))) + +private def bridgedExternalRawLogAssignVar + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {name : String} {value : Expr} + (hValue : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) : + BridgedSourceExternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource (.assignVar name value) := + .base (.base (.base (.storage (.pureBinding + (.assignVar _ _ (bridgedSourceExpr_of_exprCompileCore hValue)))))) + +private def bridgedExternalRawLogRequire + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {cond : Expr} {message : String} + (hCond : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore cond) : + BridgedSourceExternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource (.require cond message) := + .base (.base (.base (.require + (bridgedSourceRequireStmt_of_exprCompileCore hCond)))) + +private def bridgedExternalRawLogReturn + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {value : Expr} + (hValue : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) : + BridgedSourceExternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource (.return value) := + .base (.base (.base (.terminator + (.returnExternal _ (bridgedSourceExpr_of_exprCompileCore hValue))))) + +private def bridgedExternalRawLogStop + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} : + BridgedSourceExternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource .stop := + .base (.base (.base (.terminator .stop))) + +private def bridgedExternalRawLogMstore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {offset value : Expr} + (hOffset : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hValue : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) : + BridgedSourceExternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource (.mstore offset value) := + .base (.base (.memoryWrite + (.mstore _ _ (bridgedSourceExpr_of_exprCompileCore hOffset) + (bridgedSourceExpr_of_exprCompileCore hValue)))) + +private def bridgedExternalRawLogTstore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {offset value : Expr} + (hOffset : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hValue : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) : + BridgedSourceExternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource (.tstore offset value) := + .base (.base (.memoryWrite + (.tstore _ _ (bridgedSourceExpr_of_exprCompileCore hOffset) + (bridgedSourceExpr_of_exprCompileCore hValue)))) + +private def bridgedExternalRawLogIte + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} + {cond : Expr} {thenBranch elseBranch : List Stmt} + (hCond : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore cond) + (hThen : + BridgedSourceExternalRecursiveBodyWithRawLogStmts fields errors + dynamicSource thenBranch) + (hElse : + BridgedSourceExternalRecursiveBodyWithRawLogStmts fields errors + dynamicSource elseBranch) : + BridgedSourceExternalRecursiveBodyWithRawLogStmt fields errors + dynamicSource (.ite cond thenBranch elseBranch) := + .ite _ _ _ (bridgedSourceExpr_of_exprCompileCore hCond) hThen hElse + +/-- Source compile-core statement lists are covered by the recursive external + raw-log fragment: pure bindings route through the storage/body base + predicate, requires and terminators are direct body cases, and direct + memory/transient writes route through the memory-write extension. -/ +theorem bridgedSourceExternalRecursiveBodyWithRawLogStmts_of_stmtListCompileCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {scope : List String} + {stmts : List Stmt} + (hCore : _root_.Compiler.Proofs.IRGeneration.FunctionBody.StmtListCompileCore + scope stmts) : + BridgedSourceExternalRecursiveBodyWithRawLogStmts fields errors + dynamicSource stmts := by + induction hCore with + | nil => + exact .nil + | letVar hValue _hScope _hRest ih => + exact .cons (bridgedExternalRawLogLetVar hValue) ih + | assignVar hValue _hScope _hRest ih => + exact .cons (bridgedExternalRawLogAssignVar hValue) ih + | require_ hCond _hScope _hRest ih => + exact .cons (bridgedExternalRawLogRequire hCond) ih + | return_ hValue _hScope _hRest ih => + exact .cons (bridgedExternalRawLogReturn hValue) ih + | stop _hRest ih => + exact .cons bridgedExternalRawLogStop ih + | mstore hOffset _hOffsetScope hValue _hValueScope _hRest ih => + exact .cons (bridgedExternalRawLogMstore hOffset hValue) ih + | tstore hOffset _hOffsetScope hValue _hValueScope _hRest ih => + exact .cons (bridgedExternalRawLogTstore hOffset hValue) ih + +/-- Terminal compile-core statement lists have the same external native source + coverage as ordinary compile-core lists. The terminal `return`/`stop` cases + delegate their tails to the compile-core bridge exposed by the terminal + grammar. -/ +theorem bridgedSourceExternalRecursiveBodyWithRawLogStmts_of_stmtListTerminalCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {scope : List String} + {stmts : List Stmt} + (hTerminal : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.StmtListTerminalCore + scope stmts) : + BridgedSourceExternalRecursiveBodyWithRawLogStmts fields errors + dynamicSource stmts := by + induction hTerminal with + | letVar hValue _hScope _hRest ih => + exact .cons (bridgedExternalRawLogLetVar hValue) ih + | assignVar hValue _hScope _hRest ih => + exact .cons (bridgedExternalRawLogAssignVar hValue) ih + | require_ hCond _hScope _hRest ih => + exact .cons (bridgedExternalRawLogRequire hCond) ih + | return_ hValue _hScope hRest => + exact .cons (bridgedExternalRawLogReturn hValue) + (bridgedSourceExternalRecursiveBodyWithRawLogStmts_of_stmtListCompileCore + hRest) + | stop hRest => + exact .cons bridgedExternalRawLogStop + (bridgedSourceExternalRecursiveBodyWithRawLogStmts_of_stmtListCompileCore + hRest) + | mstore hOffset _hOffsetScope hValue _hValueScope _hRest ih => + exact .cons (bridgedExternalRawLogMstore hOffset hValue) ih + | tstore hOffset _hOffsetScope hValue _hValueScope _hRest ih => + exact .cons (bridgedExternalRawLogTstore hOffset hValue) ih + | ite hCond _hScope hThen hElse hRest ihThen ihElse => + exact .cons (bridgedExternalRawLogIte hCond ihThen ihElse) + (bridgedSourceExternalRecursiveBodyWithRawLogStmts_of_stmtListCompileCore + hRest) + +/-- External source bodies accepted by the compile-core grammar are native safe + bodies, so callers do not need to manually rebuild the raw-log recursive + source predicate. -/ +theorem bridgedSafeStmts_externalCompileCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {scope : List String} {stmts : List Stmt} + (hCore : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.StmtListCompileCore + scope stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames false stmts := + BridgedSafeStmts.externalRecursiveRawLog + (bridgedSourceExternalRecursiveBodyWithRawLogStmts_of_stmtListCompileCore + hCore) + +/-- External source bodies accepted by the terminal-core grammar are native safe + bodies. -/ +theorem bridgedSafeStmts_externalTerminalCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {scope : List String} {stmts : List Stmt} + (hTerminal : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.StmtListTerminalCore + scope stmts) : + BridgedSafeStmts fields errors dynamicSource internalRetNames false stmts := + BridgedSafeStmts.externalRecursiveRawLog + (bridgedSourceExternalRecursiveBodyWithRawLogStmts_of_stmtListTerminalCore + hTerminal) + +/-- External native safe-body package for the common single-word memory + preimage shape: + + `mstore(storeOffset, storeValue); let name := keccak256(hashOffset, hashSize)`. + + This is still only a native syntactic Yul-closure fact; the corresponding + source-level memory-slice hash semantics remain outside `StmtListCompileCore`. -/ +theorem bridgedSafeStmts_externalMstoreLetKeccak_of_exprCompileCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {storeOffset storeValue hashOffset hashSize : Expr} {name : String} + (hStoreOffset : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore storeOffset) + (hStoreValue : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore storeValue) + (hHashOffset : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore hashOffset) + (hHashSize : + _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore hashSize) : + BridgedSafeStmts fields errors dynamicSource internalRetNames false + [Stmt.mstore storeOffset storeValue, + Stmt.letVar name (.keccak256 hashOffset hashSize)] := + BridgedSafeStmts.externalRecursiveRawLog + (.cons + (bridgedExternalRawLogMstore hStoreOffset hStoreValue) + (.cons + (bridgedExternalRawLogLetKeccak hHashOffset hHashSize) + .nil)) + +/-- The singleton `tstore` shape exposed by `SupportedFragment.tstoreSingle` + is a native safe body whenever its offset and value are compile-core + expressions. -/ +theorem bridgedSafeStmts_tstoreSingle_of_exprCompileCore + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {offset value : Expr} + (hOffset : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore offset) + (hValue : _root_.Compiler.Proofs.IRGeneration.FunctionBody.ExprCompileCore value) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.tstore offset value] := + BridgedSafeStmts.tstore (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact bridgedSourceTstoreStmt_of_exprCompileCore hOffset hValue) + +/-- Singleton native safe-body package for a single-slot `setMapping` write. -/ +theorem bridgedSafeStmts_setMappingSingleSlot + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} {key value : Expr} + (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setMapping field key value] := + BridgedSafeStmts.mappingWrite (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceMappingWriteStmt.setMapping field hKey hValue + hMapping hSlots) + +/-- Singleton native safe-body package for a single-slot `setMappingUint` +write. -/ +theorem bridgedSafeStmts_setMappingUintSingleSlot + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} {key value : Expr} + (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setMappingUint field key value] := + BridgedSafeStmts.mappingWrite (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceMappingWriteStmt.setMappingUint field hKey hValue + hMapping hSlots) + +/-- Singleton native safe-body package for a single-slot `setMappingChain` + write. -/ +theorem bridgedSafeStmts_setMappingChainSingleSlot + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} + {keys : List Expr} {value : Expr} + (hKeys : ∀ key ∈ keys, BridgedSourceExpr key) + (hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setMappingChain field keys value] := + BridgedSafeStmts.mappingChain (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceMappingChainStmt.setMappingChain field hKeys hValue + hMapping hSlots) + +/-- Singleton native safe-body package for a single-slot `setMapping2` write. -/ +theorem bridgedSafeStmts_setMapping2SingleSlot + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} + {key1 key2 value : Expr} + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setMapping2 field key1 key2 value] := + BridgedSafeStmts.mappingWrite2 (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceMappingWrite2Stmt.setMapping2 field hKey1 hKey2 + hValue hMapping2 hSlots) + +/-- Singleton native safe-body package for a single-slot, wordOffset=0 + `setMappingWord` write. -/ +theorem bridgedSafeStmts_setMappingWordSingleSlot + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} + {key value : Expr} {wordOffset : Nat} + (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hWordOffset : wordOffset = 0) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setMappingWord field key wordOffset value] := + BridgedSafeStmts.mappingWord (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceMappingWordStmt.setMappingWord field wordOffset + hKey hValue hMapping hSlots hWordOffset) + +/-- Singleton native safe-body package for a single-slot, wordOffset=0 + `setMapping2Word` write. -/ +theorem bridgedSafeStmts_setMapping2WordSingleSlot + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} + {key1 key2 value : Expr} {wordOffset : Nat} + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hWordOffset : wordOffset = 0) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setMapping2Word field key1 key2 wordOffset value] := + BridgedSafeStmts.mapping2Word (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceMapping2WordStmt.setMapping2Word field wordOffset + hKey1 hKey2 hValue hMapping2 hSlots hWordOffset) + +/-- Singleton native safe-body package for a single-slot, wordOffset≠0 + `setMappingWord` write. -/ +theorem bridgedSafeStmts_setMappingWordSingleSlotNonzero + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot wordOffset : Nat} + {key value : Expr} + (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hNonzero : wordOffset ≠ 0) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setMappingWord field key wordOffset value] := + BridgedSafeStmts.mappingWordNonzero (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceMappingWordNonzeroStmt.setMappingWord field + hKey hValue hMapping hSlots hNonzero) + +/-- Singleton native safe-body package for a single-slot, wordOffset≠0 + `setMapping2Word` write. -/ +theorem bridgedSafeStmts_setMapping2WordSingleSlotNonzero + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot wordOffset : Nat} + {key1 key2 value : Expr} + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hNonzero : wordOffset ≠ 0) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setMapping2Word field key1 key2 wordOffset value] := + BridgedSafeStmts.mapping2WordNonzero (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceMapping2WordNonzeroStmt.setMapping2Word field + hKey1 hKey2 hValue hMapping2 hSlots hNonzero) + +/-- Singleton native safe-body package for a single-slot, wordOffset=0 + `setMappingPackedWord` write. -/ +theorem bridgedSafeStmts_setMappingPackedWordSingleSlot + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} + {key value : Expr} {wordOffset : Nat} {packed : PackedBits} + (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) + (hWordOffset : wordOffset = 0) + (hPacked : packedBitsValid packed = true) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setMappingPackedWord field key wordOffset packed value] := + BridgedSafeStmts.mappingPackedWord (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceMappingPackedWordStmt.setMappingPackedWord field + wordOffset packed hKey hValue hMapping hSlots hWordOffset hPacked) + +/-- Singleton native safe-body package for a single-slot, wordOffset=0 + `setStructMember` write. -/ +theorem bridgedSafeStmts_setStructMemberSingleSlot + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} + {key value : Expr} {memberName : String} + {members : List StructMember} {member : StructMember} + (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) + (hNotMapping2 : isMapping2 fields field = false) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hWordOffset : member.wordOffset = 0) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setStructMember field key memberName value] := + BridgedSafeStmts.structMember (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceStructMemberStmt.setStructMember field memberName + members member hKey hValue hNotMapping2 hMembers hFindMember hUnpacked + hWordOffset hMapping hSlots) + +/-- Singleton native safe-body package for a single-slot, wordOffset=0 + `setStructMember2` write. -/ +theorem bridgedSafeStmts_setStructMember2SingleSlot + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} + {key1 key2 value : Expr} {memberName : String} + {members : List StructMember} {member : StructMember} + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hWordOffset : member.wordOffset = 0) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setStructMember2 field key1 key2 memberName value] := + BridgedSafeStmts.structMember2 (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceStructMember2Stmt.setStructMember2 field memberName + members member hKey1 hKey2 hValue hMapping2 hMembers hFindMember + hUnpacked hWordOffset hSlots) + +/-- Singleton native safe-body package for a single-slot, wordOffset≠0 + `setStructMember` write. -/ +theorem bridgedSafeStmts_setStructMemberSingleSlotNonzero + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} + {key value : Expr} {memberName : String} + {members : List StructMember} {member : StructMember} + (hKey : BridgedSourceExpr key) (hValue : BridgedSourceExpr value) + (hNotMapping2 : isMapping2 fields field = false) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hNonzero : member.wordOffset ≠ 0) + (hMapping : isMapping fields field = true) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setStructMember field key memberName value] := + BridgedSafeStmts.structMemberNonzero (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceStructMemberNonzeroStmt.setStructMember field memberName + members member hKey hValue hNotMapping2 hMembers hFindMember hUnpacked + hNonzero hMapping hSlots) + +/-- Singleton native safe-body package for a single-slot, wordOffset≠0 + `setStructMember2` write. -/ +theorem bridgedSafeStmts_setStructMember2SingleSlotNonzero + {fields : List Field} {errors : List ErrorDef} + {dynamicSource : DynamicDataSource} {internalRetNames : List String} + {isInternal : Bool} {field : String} {slot : Nat} + {key1 key2 value : Expr} {memberName : String} + {members : List StructMember} {member : StructMember} + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (hValue : BridgedSourceExpr value) + (hMapping2 : isMapping2 fields field = true) + (hMembers : findStructMembers fields field = some members) + (hFindMember : findStructMember members memberName = some member) + (hUnpacked : member.packed = none) + (hNonzero : member.wordOffset ≠ 0) + (hSlots : findFieldWriteSlots fields field = some [slot]) : + BridgedSafeStmts fields errors dynamicSource internalRetNames isInternal + [Stmt.setStructMember2 field key1 key2 memberName value] := + BridgedSafeStmts.structMember2Nonzero (by + intro stmt hMem + simp only [List.mem_singleton] at hMem + subst stmt + exact BridgedSourceStructMember2NonzeroStmt.setStructMember2 field + memberName members member hKey1 hKey2 hValue hMapping2 hMembers + hFindMember hUnpacked hNonzero hSlots) /-- Every source statement list accepted by `BridgedSafeStmts` compiles to a Yul statement list accepted by `BridgedStmts`. This is the B7 aggregation @@ -11984,83 +17371,297 @@ theorem compileStmtList_always_bridged isInternal inScopeNames [] stmts = .ok out → BridgedStmts out := by intro stmts inScopeNames hSafe out hOk - cases hSafe with + induction hSafe generalizing inScopeNames out with | externalRecursiveRawLog hStmts => exact compileStmtList_external_recursive_body_with_raw_log_bridged fields events errors dynamicSource internalRetNames hStmts inScopeNames hOk | internalRecursiveRawLog hStmts => exact compileStmtList_internal_recursive_body_with_raw_log_bridged fields events errors dynamicSource internalRetNames hStmts inScopeNames hOk + | storage hStmts => + exact compileStmtList_storage_fragment_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | storageAddr hStmts => + exact compileStmtList_storageAddr_bridged fields events errors dynamicSource + internalRetNames _ _ inScopeNames hStmts hOk + | require hStmts => + exact compileStmtList_require_bridged fields events errors dynamicSource + internalRetNames _ _ inScopeNames hStmts hOk | setStorageArrayElement hStmts => exact compileStmtList_setStorageArrayElement_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mappingChain hStmts => exact compileStmtList_mappingChain_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWrite hStmts => + exact compileStmtList_mappingWrite_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mappingWriteMultiSlot hStmts => exact compileStmtList_mappingWriteMultiSlot_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWrite2 hStmts => + exact compileStmtList_mappingWrite2_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mappingWrite2MultiSlot hStmts => exact compileStmtList_mappingWrite2MultiSlot_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMember hStmts => + exact compileStmtList_structMember_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMember2 hStmts => + exact compileStmtList_structMember2_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMemberNonzero hStmts => + exact compileStmtList_structMemberNonzero_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMember2Nonzero hStmts => + exact compileStmtList_structMember2Nonzero_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | structMemberMultiSlot hStmts => exact compileStmtList_structMemberMultiSlot_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | structMember2MultiSlot hStmts => exact compileStmtList_structMember2MultiSlot_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWord hStmts => + exact compileStmtList_mappingWord_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mapping2Word hStmts => + exact compileStmtList_mapping2Word_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWordNonzero hStmts => + exact compileStmtList_mappingWordNonzero_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mapping2WordNonzero hStmts => + exact compileStmtList_mapping2WordNonzero_bridged fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mappingWordMultiSlot hStmts => exact compileStmtList_mappingWordMultiSlot_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mapping2WordMultiSlot hStmts => exact compileStmtList_mapping2WordMultiSlot_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mappingWordMultiSlotNonzero hStmts => exact compileStmtList_mappingWordMultiSlotNonzero_bridged fields events - errors dynamicSource internalRetNames isInternal stmts inScopeNames + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mapping2WordMultiSlotNonzero hStmts => exact compileStmtList_mapping2WordMultiSlotNonzero_bridged fields events - errors dynamicSource internalRetNames isInternal stmts inScopeNames + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | structMemberMultiSlotNonzero hStmts => exact compileStmtList_structMemberMultiSlotNonzero_bridged fields events - errors dynamicSource internalRetNames isInternal stmts inScopeNames + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | structMember2MultiSlotNonzero hStmts => exact compileStmtList_structMember2MultiSlotNonzero_bridged fields events - errors dynamicSource internalRetNames isInternal stmts inScopeNames + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mappingPackedWord hStmts => exact compileStmtList_mappingPackedWord_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mappingPackedWordNonzero hStmts => exact compileStmtList_mappingPackedWordNonzero_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mappingPackedWordMultiSlot hStmts => exact compileStmtList_mappingPackedWordMultiSlot_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | mappingPackedWordMultiSlotNonzero hStmts => exact compileStmtList_mappingPackedWordMultiSlotNonzero_bridged fields - events errors dynamicSource internalRetNames isInternal stmts inScopeNames + events errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | returnValuesExternal hStmts => exact compileStmtList_returnValuesExternal_bridged fields events errors - dynamicSource internalRetNames stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ inScopeNames hStmts hOk | returnValuesInternal hStmts => exact compileStmtList_returnValuesInternal_bridged fields events errors - dynamicSource internalRetNames stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ inScopeNames hStmts hOk | mstore hStmts => exact compileStmtList_mstore_bridged fields events errors dynamicSource - internalRetNames isInternal stmts inScopeNames hStmts hOk + internalRetNames _ _ inScopeNames hStmts hOk | tstore hStmts => exact compileStmtList_tstore_bridged fields events errors dynamicSource - internalRetNames isInternal stmts inScopeNames hStmts hOk + internalRetNames _ _ inScopeNames hStmts hOk | storageArrayPush hStmts => exact compileStmtList_storageArrayPush_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk | storageArrayPop hStmts => exact compileStmtList_storageArrayPop_bridged fields events errors - dynamicSource internalRetNames isInternal stmts inScopeNames hStmts hOk + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | append hPfx hSfx ihPfx ihSfx => + rename_i localIsInternal pfx sfx + rw [compileStmtList_append_eq fields events errors dynamicSource + internalRetNames localIsInternal inScopeNames [] pfx sfx] at hOk + cases hPfxCompile : compileStmtList fields events errors dynamicSource + internalRetNames localIsInternal inScopeNames [] pfx with + | error err => + simp [hPfxCompile] at hOk + | ok pfxOut => + simp [hPfxCompile] at hOk + cases hSfxCompile : compileStmtList fields events errors dynamicSource + internalRetNames localIsInternal + ((List.map collectStmtNames pfx).reverse.flatten ++ inScopeNames) + [] sfx with + | error err => + simp [hSfxCompile] at hOk + | ok sfxOut => + simp [hSfxCompile, Pure.pure, Except.pure] at hOk + subst out + exact BridgedStmts_append + (ihPfx inScopeNames hPfxCompile) + (ihSfx + ((List.map collectStmtNames pfx).reverse.flatten ++ + inScopeNames) + hSfxCompile) + +theorem compileStmtList_always_noFuncDefs + (fields : List Field) (events : List EventDef) (errors : List ErrorDef) + (dynamicSource : DynamicDataSource) (internalRetNames : List String) + (isInternal : Bool) : + ∀ (stmts : List Stmt) (inScopeNames : List String), + BridgedSafeStmts fields errors dynamicSource internalRetNames + isInternal stmts → + ∀ {out : List YulStmt}, + compileStmtList fields events errors dynamicSource internalRetNames + isInternal inScopeNames [] stmts = .ok out → + Native.yulStmtsContainFuncDef out = false := by + intro stmts inScopeNames hSafe out hOk + induction hSafe generalizing inScopeNames out with + | externalRecursiveRawLog hStmts => + exact compileStmtList_external_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames hStmts inScopeNames hOk + | internalRecursiveRawLog hStmts => + exact compileStmtList_internal_recursive_body_with_raw_log_noFuncDefs + fields events errors dynamicSource internalRetNames hStmts inScopeNames hOk + | storage hStmts => + exact compileStmtList_storage_fragment_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | storageAddr hStmts => + exact compileStmtList_storageAddr_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | require hStmts => + exact compileStmtList_require_noFuncDefs fields events errors dynamicSource + internalRetNames _ _ inScopeNames hStmts hOk + | setStorageArrayElement hStmts => + exact compileStmtList_setStorageArrayElement_noFuncDefs fields events + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingChain hStmts => + exact compileStmtList_mappingChain_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWrite hStmts => + exact compileStmtList_mappingWrite_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWriteMultiSlot hStmts => + exact compileStmtList_mappingWriteMultiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWrite2 hStmts => + exact compileStmtList_mappingWrite2_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWrite2MultiSlot hStmts => + exact compileStmtList_mappingWrite2MultiSlot_noFuncDefs fields events + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMember hStmts => + exact compileStmtList_structMember_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMember2 hStmts => + exact compileStmtList_structMember2_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMemberNonzero hStmts => + exact compileStmtList_structMemberNonzero_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMember2Nonzero hStmts => + exact compileStmtList_structMember2Nonzero_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMemberMultiSlot hStmts => + exact compileStmtList_structMemberMultiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMember2MultiSlot hStmts => + exact compileStmtList_structMember2MultiSlot_noFuncDefs fields events + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWord hStmts => + exact compileStmtList_mappingWord_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mapping2Word hStmts => + exact compileStmtList_mapping2Word_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWordNonzero hStmts => + exact compileStmtList_mappingWordNonzero_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mapping2WordNonzero hStmts => + exact compileStmtList_mapping2WordNonzero_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWordMultiSlot hStmts => + exact compileStmtList_mappingWordMultiSlot_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mapping2WordMultiSlot hStmts => + exact compileStmtList_mapping2WordMultiSlot_noFuncDefs fields events + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingWordMultiSlotNonzero hStmts => + exact compileStmtList_mappingWordMultiSlotNonzero_noFuncDefs fields events + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mapping2WordMultiSlotNonzero hStmts => + exact compileStmtList_mapping2WordMultiSlotNonzero_noFuncDefs fields + events errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMemberMultiSlotNonzero hStmts => + exact compileStmtList_structMemberMultiSlotNonzero_noFuncDefs fields + events errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | structMember2MultiSlotNonzero hStmts => + exact compileStmtList_structMember2MultiSlotNonzero_noFuncDefs fields + events errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingPackedWord hStmts => + exact compileStmtList_mappingPackedWord_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingPackedWordNonzero hStmts => + exact compileStmtList_mappingPackedWordNonzero_noFuncDefs fields events + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingPackedWordMultiSlot hStmts => + exact compileStmtList_mappingPackedWordMultiSlot_noFuncDefs fields events + errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | mappingPackedWordMultiSlotNonzero hStmts => + exact compileStmtList_mappingPackedWordMultiSlotNonzero_noFuncDefs fields + events errors dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | returnValuesExternal hStmts => + exact compileStmtList_returnValuesExternal_noFuncDefs fields events errors + dynamicSource internalRetNames _ inScopeNames hStmts hOk + | returnValuesInternal hStmts => + exact compileStmtList_returnValuesInternal_noFuncDefs fields events errors + dynamicSource internalRetNames _ inScopeNames hStmts hOk + | mstore hStmts => + exact compileStmtList_mstore_noFuncDefs fields events errors dynamicSource + internalRetNames _ _ inScopeNames hStmts hOk + | tstore hStmts => + exact compileStmtList_tstore_noFuncDefs fields events errors dynamicSource + internalRetNames _ _ inScopeNames hStmts hOk + | storageArrayPush hStmts => + exact compileStmtList_storageArrayPush_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | storageArrayPop hStmts => + exact compileStmtList_storageArrayPop_noFuncDefs fields events errors + dynamicSource internalRetNames _ _ inScopeNames hStmts hOk + | append hPfx hSfx ihPfx ihSfx => + rename_i localIsInternal pfx sfx + rw [compileStmtList_append_eq fields events errors dynamicSource + internalRetNames localIsInternal inScopeNames [] pfx sfx] at hOk + cases hPfxCompile : compileStmtList fields events errors dynamicSource + internalRetNames localIsInternal inScopeNames [] pfx with + | error err => + simp [hPfxCompile] at hOk + | ok pfxOut => + simp [hPfxCompile] at hOk + cases hSfxCompile : compileStmtList fields events errors dynamicSource + internalRetNames localIsInternal + ((List.map collectStmtNames pfx).reverse.flatten ++ inScopeNames) + [] sfx with + | error err => + simp [hSfxCompile] at hOk + | ok sfxOut => + simp [hSfxCompile, Pure.pure, Except.pure] at hOk + subst out + rw [Native.yulStmtsContainFuncDef_append] + simp [ihPfx inScopeNames hPfxCompile, + ihSfx + ((List.map collectStmtNames pfx).reverse.flatten ++ + inScopeNames) + hSfxCompile] end Compiler.Proofs.YulGeneration.Backends diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean index 4f67fd63d..39558dc3a 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean @@ -1,5 +1,7 @@ +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgePredicates import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanAdapter +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanPureBuiltinLemmas import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanSignedArithSpec import Mathlib.Data.Nat.Bitwise @@ -22,9 +24,9 @@ private theorem uint256_ofNat_mod_evmModulus (n : Nat) : private theorem verity_eval_add_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "add" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "add" [a, b] = some ((a + b) % evmModulus) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_add_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "add" [a, b] = @@ -35,9 +37,9 @@ private theorem bridge_eval_add_normalized (a b : Nat) : private theorem verity_eval_sub_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "sub" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "sub" [a, b] = some ((evmModulus + a % evmModulus - b % evmModulus) % evmModulus) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_sub_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "sub" [a, b] = @@ -50,9 +52,9 @@ private theorem bridge_eval_sub_normalized (a b : Nat) : private theorem verity_eval_mul_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "mul" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "mul" [a, b] = some ((a * b) % evmModulus) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_mul_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "mul" [a, b] = @@ -63,9 +65,9 @@ private theorem bridge_eval_mul_normalized (a b : Nat) : private theorem verity_eval_div_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "div" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "div" [a, b] = (if b % evmModulus = 0 then some 0 else some ((a % evmModulus) / (b % evmModulus))) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_div_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "div" [a, b] = @@ -80,9 +82,9 @@ private theorem bridge_eval_div_normalized (a b : Nat) : private theorem verity_eval_mod_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "mod" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "mod" [a, b] = (if b % evmModulus = 0 then some 0 else some ((a % evmModulus) % (b % evmModulus))) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_mod_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "mod" [a, b] = @@ -111,9 +113,9 @@ private theorem bridge_eval_mod_normalized (a b : Nat) : private theorem verity_eval_eq_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "eq" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "eq" [a, b] = some (if a % evmModulus = b % evmModulus then 1 else 0) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_eq_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "eq" [a, b] = @@ -122,9 +124,9 @@ private theorem bridge_eval_eq_normalized (a b : Nat) : private theorem verity_eval_iszero_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a : Nat) : - evalBuiltinCall storage sender selector calldata "iszero" [a] = + legacyEvalBuiltinCall storage sender selector calldata "iszero" [a] = some (if a % evmModulus = 0 then 1 else 0) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_iszero_normalized (a : Nat) : evalPureBuiltinViaEvmYulLean "iszero" [a] = @@ -134,9 +136,9 @@ private theorem bridge_eval_iszero_normalized (a : Nat) : set_option maxHeartbeats 2000000 in private theorem verity_eval_lt_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "lt" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "lt" [a, b] = some (if a % evmModulus < b % evmModulus then 1 else 0) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_lt_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "lt" [a, b] = @@ -146,9 +148,9 @@ private theorem bridge_eval_lt_normalized (a b : Nat) : set_option maxHeartbeats 2000000 in private theorem verity_eval_gt_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "gt" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "gt" [a, b] = some (if a % evmModulus > b % evmModulus then 1 else 0) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_gt_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "gt" [a, b] = @@ -293,14 +295,14 @@ private theorem bridge_eval_shr_normalized (shift value : Nat) : @[simp] theorem evalBuiltinCall_add_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "add" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "add" [a, b] = evalPureBuiltinViaEvmYulLean "add" [a, b] := by rw [verity_eval_add_normalized, bridge_eval_add_normalized] simp [EvmYul.UInt256.size, evmModulus] @[simp] theorem evalBuiltinCall_sub_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "sub" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "sub" [a, b] = evalPureBuiltinViaEvmYulLean "sub" [a, b] := by rw [verity_eval_sub_normalized, bridge_eval_sub_normalized] have hb : b % evmModulus ≤ evmModulus := by @@ -312,21 +314,21 @@ private theorem bridge_eval_shr_normalized (shift value : Nat) : @[simp] theorem evalBuiltinCall_mul_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "mul" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "mul" [a, b] = evalPureBuiltinViaEvmYulLean "mul" [a, b] := by rw [verity_eval_mul_normalized, bridge_eval_mul_normalized] simp [EvmYul.UInt256.size, evmModulus] @[simp] theorem evalBuiltinCall_div_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "div" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "div" [a, b] = evalPureBuiltinViaEvmYulLean "div" [a, b] := by rw [verity_eval_div_normalized, bridge_eval_div_normalized] simp [EvmYul.UInt256.size, evmModulus] @[simp] theorem evalBuiltinCall_mod_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "mod" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "mod" [a, b] = evalPureBuiltinViaEvmYulLean "mod" [a, b] := by rw [verity_eval_mod_normalized, bridge_eval_mod_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -335,7 +337,7 @@ private theorem bridge_eval_shr_normalized (shift value : Nat) : EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_eq_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "eq" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "eq" [a, b] = evalPureBuiltinViaEvmYulLean "eq" [a, b] := by rw [verity_eval_eq_normalized, bridge_eval_eq_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -344,7 +346,7 @@ EVMYulLean UInt256 semantics on all inputs. -/ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_iszero_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a : Nat) : - evalBuiltinCall storage sender selector calldata "iszero" [a] = + legacyEvalBuiltinCall storage sender selector calldata "iszero" [a] = evalPureBuiltinViaEvmYulLean "iszero" [a] := by rw [verity_eval_iszero_normalized, bridge_eval_iszero_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -353,7 +355,7 @@ EVMYulLean UInt256 semantics on all inputs. -/ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_lt_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "lt" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "lt" [a, b] = evalPureBuiltinViaEvmYulLean "lt" [a, b] := by rw [verity_eval_lt_normalized, bridge_eval_lt_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -362,7 +364,7 @@ EVMYulLean UInt256 semantics on all inputs. -/ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_gt_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "gt" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "gt" [a, b] = evalPureBuiltinViaEvmYulLean "gt" [a, b] := by rw [verity_eval_gt_normalized, bridge_eval_gt_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -371,10 +373,10 @@ EVMYulLean UInt256 semantics on all inputs. -/ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_and_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "and" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "and" [a, b] = evalPureBuiltinViaEvmYulLean "and" [a, b] := by - rw [show evalBuiltinCall storage sender selector calldata "and" [a, b] = - some (a % evmModulus &&& b % evmModulus) by simp [evalBuiltinCall, evalBuiltinCallWithContext]] + rw [show legacyEvalBuiltinCall storage sender selector calldata "and" [a, b] = + some (a % evmModulus &&& b % evmModulus) by simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext]] rw [bridge_eval_and_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -382,10 +384,10 @@ EVMYulLean UInt256 semantics on all inputs. -/ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_or_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "or" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "or" [a, b] = evalPureBuiltinViaEvmYulLean "or" [a, b] := by - rw [show evalBuiltinCall storage sender selector calldata "or" [a, b] = - some (a % evmModulus ||| b % evmModulus) by simp [evalBuiltinCall, evalBuiltinCallWithContext]] + rw [show legacyEvalBuiltinCall storage sender selector calldata "or" [a, b] = + some (a % evmModulus ||| b % evmModulus) by simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext]] rw [bridge_eval_or_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -393,7 +395,7 @@ EVMYulLean UInt256 semantics on all inputs. -/ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_xor_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "xor" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "xor" [a, b] = evalPureBuiltinViaEvmYulLean "xor" [a, b] := by change some (Nat.bitwise bne (a % evmModulus) (b % evmModulus)) = evalPureBuiltinViaEvmYulLean "xor" [a, b] @@ -405,7 +407,7 @@ EVMYulLean UInt256 semantics on all inputs. -/ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_not_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a : Nat) : - evalBuiltinCall storage sender selector calldata "not" [a] = + legacyEvalBuiltinCall storage sender selector calldata "not" [a] = evalPureBuiltinViaEvmYulLean "not" [a] := by change some (a % evmModulus ^^^ (evmModulus - 1)) = evalPureBuiltinViaEvmYulLean "not" [a] @@ -416,13 +418,13 @@ EVMYulLean UInt256 semantics on all inputs. -/ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_shl_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (shift value : Nat) : - evalBuiltinCall storage sender selector calldata "shl" [shift, value] = + legacyEvalBuiltinCall storage sender selector calldata "shl" [shift, value] = evalPureBuiltinViaEvmYulLean "shl" [shift, value] := by - rw [show evalBuiltinCall storage sender selector calldata "shl" [shift, value] = + rw [show legacyEvalBuiltinCall storage sender selector calldata "shl" [shift, value] = (if shift % evmModulus < 256 then some (((value % evmModulus) * 2 ^ (shift % evmModulus)) % evmModulus) else - some 0) by simp [evalBuiltinCall, evalBuiltinCallWithContext]] + some 0) by simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext]] rw [bridge_eval_shl_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -430,119 +432,119 @@ EVMYulLean UInt256 semantics on all inputs. -/ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_shr_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (shift value : Nat) : - evalBuiltinCall storage sender selector calldata "shr" [shift, value] = + legacyEvalBuiltinCall storage sender selector calldata "shr" [shift, value] = evalPureBuiltinViaEvmYulLean "shr" [shift, value] := by - rw [show evalBuiltinCall storage sender selector calldata "shr" [shift, value] = + rw [show legacyEvalBuiltinCall storage sender selector calldata "shr" [shift, value] = (if shift % evmModulus < 256 then some ((value % evmModulus) / 2 ^ (shift % evmModulus)) else - some 0) by simp [evalBuiltinCall, evalBuiltinCallWithContext]] + some 0) by simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext]] rw [bridge_eval_shr_normalized] simp [EvmYul.UInt256.size, evmModulus] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_add_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "add" [a, b] = - evalBuiltinCall storage sender selector calldata "add" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "add" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_add_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_sub_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "sub" [a, b] = - evalBuiltinCall storage sender selector calldata "sub" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "sub" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_sub_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_mul_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "mul" [a, b] = - evalBuiltinCall storage sender selector calldata "mul" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "mul" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_mul_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_div_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "div" [a, b] = - evalBuiltinCall storage sender selector calldata "div" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "div" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_div_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_mod_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "mod" [a, b] = - evalBuiltinCall storage sender selector calldata "mod" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "mod" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_mod_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_eq_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "eq" [a, b] = - evalBuiltinCall storage sender selector calldata "eq" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "eq" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_eq_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_iszero_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "iszero" [a] = - evalBuiltinCall storage sender selector calldata "iszero" [a] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "iszero" [a] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_iszero_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_lt_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "lt" [a, b] = - evalBuiltinCall storage sender selector calldata "lt" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "lt" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_lt_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_gt_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "gt" [a, b] = - evalBuiltinCall storage sender selector calldata "gt" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "gt" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_gt_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_and_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "and" [a, b] = - evalBuiltinCall storage sender selector calldata "and" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "and" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_and_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_or_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "or" [a, b] = - evalBuiltinCall storage sender selector calldata "or" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "or" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_or_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_xor_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "xor" [a, b] = - evalBuiltinCall storage sender selector calldata "xor" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "xor" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_xor_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_not_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "not" [a] = - evalBuiltinCall storage sender selector calldata "not" [a] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "not" [a] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_not_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_shl_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (shift value : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "shl" [shift, value] = - evalBuiltinCall storage sender selector calldata "shl" [shift, value] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "shl" [shift, value] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_shl_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_shr_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (shift value : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "shr" [shift, value] = - evalBuiltinCall storage sender selector calldata "shr" [shift, value] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "shr" [shift, value] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_shr_bridge] /-! ## Addmod / Mulmod Bridge Lemmas @@ -553,9 +555,9 @@ The key proof obligation is showing that the intermediate result is already private theorem verity_eval_addmod_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b n : Nat) : - evalBuiltinCall storage sender selector calldata "addmod" [a, b, n] = + legacyEvalBuiltinCall storage sender selector calldata "addmod" [a, b, n] = (if n % evmModulus = 0 then some 0 else some (((a % evmModulus) + (b % evmModulus)) % (n % evmModulus))) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem eq0_true_of_val_eq_zero (x : EvmYul.UInt256) (h : x.val = 0) : EvmYul.UInt256.eq0 x = true := by @@ -612,9 +614,9 @@ private theorem bridge_eval_addmod_normalized (a b n : Nat) : private theorem verity_eval_mulmod_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b n : Nat) : - evalBuiltinCall storage sender selector calldata "mulmod" [a, b, n] = + legacyEvalBuiltinCall storage sender selector calldata "mulmod" [a, b, n] = (if n % evmModulus = 0 then some 0 else some (((a % evmModulus) * (b % evmModulus)) % (n % evmModulus))) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_mulmod_normalized (a b n : Nat) : evalPureBuiltinViaEvmYulLean "mulmod" [a, b, n] = @@ -647,7 +649,7 @@ private theorem bridge_eval_mulmod_normalized (a b n : Nat) : EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_addmod_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b n : Nat) : - evalBuiltinCall storage sender selector calldata "addmod" [a, b, n] = + legacyEvalBuiltinCall storage sender selector calldata "addmod" [a, b, n] = evalPureBuiltinViaEvmYulLean "addmod" [a, b, n] := by rw [verity_eval_addmod_normalized, bridge_eval_addmod_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -656,7 +658,7 @@ EVMYulLean UInt256 semantics on all inputs. -/ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_mulmod_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b n : Nat) : - evalBuiltinCall storage sender selector calldata "mulmod" [a, b, n] = + legacyEvalBuiltinCall storage sender selector calldata "mulmod" [a, b, n] = evalPureBuiltinViaEvmYulLean "mulmod" [a, b, n] := by rw [verity_eval_mulmod_normalized, bridge_eval_mulmod_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -664,15 +666,15 @@ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_addmod_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b n : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "addmod" [a, b, n] = - evalBuiltinCall storage sender selector calldata "addmod" [a, b, n] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "addmod" [a, b, n] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_addmod_bridge] @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_mulmod_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b n : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "mulmod" [a, b, n] = - evalBuiltinCall storage sender selector calldata "mulmod" [a, b, n] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "mulmod" [a, b, n] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_mulmod_bridge] @@ -692,10 +694,10 @@ private theorem nat_land_0xFF (n : Nat) : Nat.land n 255 = n % 256 := by set_option maxHeartbeats 4000000 in private theorem verity_eval_byte_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (i x : Nat) : - evalBuiltinCall storage sender selector calldata "byte" [i, x] = + legacyEvalBuiltinCall storage sender selector calldata "byte" [i, x] = (if i % evmModulus > 31 then some 0 else some ((x % evmModulus / 2 ^ ((31 - i % evmModulus) * 8)) % 256)) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] set_option maxHeartbeats 16000000 in private theorem bridge_eval_byte_normalized (i x : Nat) : @@ -762,7 +764,7 @@ private theorem bridge_eval_byte_normalized (i x : Nat) : EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_byte_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (i x : Nat) : - evalBuiltinCall storage sender selector calldata "byte" [i, x] = + legacyEvalBuiltinCall storage sender selector calldata "byte" [i, x] = evalPureBuiltinViaEvmYulLean "byte" [i, x] := by rw [verity_eval_byte_normalized, bridge_eval_byte_normalized] simp [EvmYul.UInt256.size, evmModulus] @@ -770,8 +772,8 @@ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_byte_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (i x : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "byte" [i, x] = - evalBuiltinCall storage sender selector calldata "byte" [i, x] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "byte" [i, x] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_byte_bridge] /-! ## Signed Comparison Bridge Proofs (slt, sgt) @@ -783,16 +785,16 @@ These proofs bridge between Verity's `Int256.toInt`-based signed comparison set_option maxHeartbeats 4000000 in /-- Helper: Verity's signed less-than on raw Nat inputs reduces to a comparison -via `Int256.toInt`. This normalizes `evalBuiltinCallWithContext` for `slt`. -/ +via `Int256.toInt`. This normalizes `legacyEvalBuiltinCallWithContext` for `slt`. -/ private theorem verity_eval_slt_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "slt" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "slt" [a, b] = some (if Verity.Core.Int256.toInt (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (a % evmModulus))) < Verity.Core.Int256.toInt (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (b % evmModulus))) then 1 else 0) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] /-- Helper: EVMYulLean's slt reduces to a Bool-valued sign-bit case split. -/ private theorem bridge_eval_slt_normalized (a b : Nat) : @@ -803,16 +805,16 @@ private theorem bridge_eval_slt_normalized (a b : Nat) : set_option maxHeartbeats 4000000 in /-- Helper: Verity's signed greater-than on raw Nat inputs reduces to a comparison -via `Int256.toInt`. This normalizes `evalBuiltinCallWithContext` for `sgt`. -/ +via `Int256.toInt`. This normalizes `legacyEvalBuiltinCallWithContext` for `sgt`. -/ private theorem verity_eval_sgt_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "sgt" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "sgt" [a, b] = some (if Verity.Core.Int256.toInt (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (b % evmModulus))) < Verity.Core.Int256.toInt (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (a % evmModulus))) then 1 else 0) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] /-- Helper: EVMYulLean's sgt reduces to a Nat value. -/ private theorem bridge_eval_sgt_normalized (a b : Nat) : @@ -894,7 +896,7 @@ private theorem slt_int256_eq_sltBool (a b : Nat) (ha : a < evmModulus) (hb : b EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_slt_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "slt" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "slt" [a, b] = evalPureBuiltinViaEvmYulLean "slt" [a, b] := by rw [verity_eval_slt_normalized, bridge_eval_slt_normalized] have ha : a % evmModulus < evmModulus := Nat.mod_lt a (by unfold evmModulus; omega) @@ -918,8 +920,8 @@ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_slt_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "slt" [a, b] = - evalBuiltinCall storage sender selector calldata "slt" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "slt" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_slt_bridge] set_option maxHeartbeats 32000000 in @@ -955,7 +957,7 @@ private theorem sgt_int256_eq_sgtBool (a b : Nat) (ha : a < evmModulus) (hb : b EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_sgt_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "sgt" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "sgt" [a, b] = evalPureBuiltinViaEvmYulLean "sgt" [a, b] := by rw [verity_eval_sgt_normalized, bridge_eval_sgt_normalized] have ha : a % evmModulus < evmModulus := Nat.mod_lt a (by unfold evmModulus; omega) @@ -979,8 +981,8 @@ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_sgt_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "sgt" [a, b] = - evalBuiltinCall storage sender selector calldata "sgt" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "sgt" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_sgt_bridge] /-! ## Exp Bridge Proof @@ -995,9 +997,9 @@ the same result. This needs an induction proof matching the loop invariants. -/ private theorem verity_eval_exp_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "exp" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "exp" [a, b] = some (natModPow (a % evmModulus) (b % evmModulus) evmModulus) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_exp_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "exp" [a, b] = @@ -1105,7 +1107,7 @@ private theorem exp_natModPow_eq_uint256Exp (a b : Nat) EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCall_exp_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "exp" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "exp" [a, b] = evalPureBuiltinViaEvmYulLean "exp" [a, b] := by rw [verity_eval_exp_normalized, bridge_eval_exp_normalized] have ha : a % evmModulus < evmModulus := Nat.mod_lt a (by unfold evmModulus; omega) @@ -1122,8 +1124,8 @@ EVMYulLean UInt256 semantics on all inputs. -/ @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_exp_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "exp" [a, b] = - evalBuiltinCall storage sender selector calldata "exp" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "exp" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_exp_bridge] /-! ## Sdiv Bridge Proof @@ -1135,11 +1137,11 @@ implement EVM SDIV: signed division with truncation toward zero, where private theorem verity_eval_sdiv_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "sdiv" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "sdiv" [a, b] = some (Verity.Core.Int256.div (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (a % evmModulus))) (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (b % evmModulus)))).toUint256.val := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_sdiv_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "sdiv" [a, b] = @@ -1366,7 +1368,7 @@ private theorem sdiv_int256_eq_uint256Sdiv (a b : Nat) /-- Universal bridge theorem for `sdiv`. -/ @[simp] theorem evalBuiltinCall_sdiv_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "sdiv" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "sdiv" [a, b] = evalPureBuiltinViaEvmYulLean "sdiv" [a, b] := by rw [verity_eval_sdiv_normalized, bridge_eval_sdiv_normalized] have ha : a % evmModulus < evmModulus := Nat.mod_lt a (by unfold evmModulus; omega) @@ -1388,8 +1390,8 @@ private theorem sdiv_int256_eq_uint256Sdiv (a b : Nat) @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_sdiv_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "sdiv" [a, b] = - evalBuiltinCall storage sender selector calldata "sdiv" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "sdiv" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_sdiv_bridge] /-! ## Smod Bridge Proof @@ -1399,11 +1401,11 @@ with EVMYulLean's `UInt256.smod` (sign/abs decomposition with `sgn`/`toSigned`). private theorem verity_eval_smod_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "smod" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "smod" [a, b] = some (Verity.Core.Int256.mod (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (a % evmModulus))) (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (b % evmModulus)))).toUint256.val := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_smod_normalized (a b : Nat) : evalPureBuiltinViaEvmYulLean "smod" [a, b] = @@ -1913,7 +1915,7 @@ private theorem smod_int256_eq_uint256Smod (a b : Nat) /-- Universal bridge theorem for `smod`. -/ @[simp] theorem evalBuiltinCall_smod_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "smod" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "smod" [a, b] = evalPureBuiltinViaEvmYulLean "smod" [a, b] := by rw [verity_eval_smod_normalized, bridge_eval_smod_normalized] have ha : a % evmModulus < evmModulus := Nat.mod_lt a (by unfold evmModulus; omega) @@ -1935,8 +1937,8 @@ private theorem smod_int256_eq_uint256Smod (a b : Nat) @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_smod_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "smod" [a, b] = - evalBuiltinCall storage sender selector calldata "smod" [a, b] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "smod" [a, b] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_smod_bridge] /-! ## SAR (Signed Arithmetic Right Shift) Bridge Proof @@ -1946,11 +1948,11 @@ with EVMYulLean's `UInt256.sar` (complement-shift-complement for negatives). -/ private theorem verity_eval_sar_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (shift value : Nat) : - evalBuiltinCall storage sender selector calldata "sar" [shift, value] = + legacyEvalBuiltinCall storage sender selector calldata "sar" [shift, value] = some (Verity.Core.Int256.sar (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (shift % evmModulus))) (Verity.Core.Int256.ofUint256 (Verity.Core.Uint256.ofNat (value % evmModulus)))).toUint256.val := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_sar_normalized (shift value : Nat) : evalPureBuiltinViaEvmYulLean "sar" [shift, value] = @@ -2288,7 +2290,7 @@ private theorem sar_int256_eq_uint256Sar (shift value : Nat) /-- Universal bridge theorem for `sar`. -/ @[simp] theorem evalBuiltinCall_sar_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (shift value : Nat) : - evalBuiltinCall storage sender selector calldata "sar" [shift, value] = + legacyEvalBuiltinCall storage sender selector calldata "sar" [shift, value] = evalPureBuiltinViaEvmYulLean "sar" [shift, value] := by rw [verity_eval_sar_normalized, bridge_eval_sar_normalized] have hs : shift % evmModulus < evmModulus := Nat.mod_lt shift (by unfold evmModulus; omega) @@ -2310,8 +2312,8 @@ private theorem sar_int256_eq_uint256Sar (shift value : Nat) @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_sar_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (shift value : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "sar" [shift, value] = - evalBuiltinCall storage sender selector calldata "sar" [shift, value] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "sar" [shift, value] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_sar_bridge] /-! ## Signextend Bridge Proof @@ -2322,11 +2324,11 @@ Both implement EVM SIGNEXTEND: extending the sign bit at byte position `b`. -/ private theorem verity_eval_signextend_normalized (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (byteIdx value : Nat) : - evalBuiltinCall storage sender selector calldata "signextend" [byteIdx, value] = + legacyEvalBuiltinCall storage sender selector calldata "signextend" [byteIdx, value] = some (Verity.Core.Uint256.signextend (Verity.Core.Uint256.ofNat (byteIdx % evmModulus)) (Verity.Core.Uint256.ofNat (value % evmModulus))).val := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] private theorem bridge_eval_signextend_normalized (byteIdx value : Nat) : evalPureBuiltinViaEvmYulLean "signextend" [byteIdx, value] = @@ -2612,7 +2614,7 @@ private theorem signextend_uint256_eq (byteIdx value : Nat) /-- Universal bridge theorem for `signextend`. -/ @[simp] theorem evalBuiltinCall_signextend_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (byteIdx value : Nat) : - evalBuiltinCall storage sender selector calldata "signextend" [byteIdx, value] = + legacyEvalBuiltinCall storage sender selector calldata "signextend" [byteIdx, value] = evalPureBuiltinViaEvmYulLean "signextend" [byteIdx, value] := by rw [verity_eval_signextend_normalized, bridge_eval_signextend_normalized] have hb : byteIdx % evmModulus < evmModulus := Nat.mod_lt byteIdx (by unfold evmModulus; omega) @@ -2634,8 +2636,8 @@ private theorem signextend_uint256_eq (byteIdx value : Nat) @[simp] theorem evalBuiltinCallWithBackend_evmYulLean_signextend_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (byteIdx value : Nat) : evalBuiltinCallWithBackend .evmYulLean storage sender selector calldata "signextend" [byteIdx, value] = - evalBuiltinCall storage sender selector calldata "signextend" [byteIdx, value] := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean, + legacyEvalBuiltinCall storage sender selector calldata "signextend" [byteIdx, value] := by + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean, evalBuiltinCall_signextend_bridge] /-! ## State-dependent Builtin Fallthrough Lemmas @@ -2735,32 +2737,32 @@ fallback covers all builtins. -/ on the selector/calldata context rather than only on argument words. -/ @[simp] theorem evalBuiltinCall_calldataload_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (offset : Nat) : - evalBuiltinCall storage sender selector calldata "calldataload" [offset] = + legacyEvalBuiltinCall storage sender selector calldata "calldataload" [offset] = evalBuiltinCallViaEvmYulLean storage sender selector calldata "calldataload" [offset] := by - simp [evalBuiltinCall, evalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] /-- `sload` is bridged at the full adapter boundary: the `.evmYulLean` path routes through `abstractLoadStorageOrMapping`, the same helper Verity's - `evalBuiltinCallWithContext` uses. The EVMYulLean-state correspondence of + `legacyEvalBuiltinCallWithContext` uses. The EVMYulLean-state correspondence of that helper is witnessed by `storageLookup_projectStorage` in `EvmYulLeanStateBridge.lean`. -/ @[simp] theorem evalBuiltinCall_sload_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (slot : Nat) : - evalBuiltinCall storage sender selector calldata "sload" [slot] = + legacyEvalBuiltinCall storage sender selector calldata "sload" [slot] = evalBuiltinCallViaEvmYulLean storage sender selector calldata "sload" [slot] := by - simp [evalBuiltinCall, evalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] /-- `mappingSlot` is bridged at the full adapter boundary: the `.evmYulLean` path routes through `abstractMappingSlot`, the same keccak-faithful Solidity mapping-slot derivation (`keccak256(abi.encode(key, baseSlot))`) - that Verity's `evalBuiltinCallWithContext` uses. Because both backends + that Verity's `legacyEvalBuiltinCallWithContext` uses. Because both backends ultimately invoke the same kernel-computable `KeccakEngine.keccak256`, the two sides are definitionally equal. -/ @[simp] theorem evalBuiltinCall_mappingSlot_bridge (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (base key : Nat) : - evalBuiltinCall storage sender selector calldata "mappingSlot" [base, key] = + legacyEvalBuiltinCall storage sender selector calldata "mappingSlot" [base, key] = evalBuiltinCallViaEvmYulLean storage sender selector calldata "mappingSlot" [base, key] := by - simp [evalBuiltinCall, evalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] /-- `evalPureBuiltinViaEvmYulLean` returns `none` for `calldatasize`. -/ @[simp] theorem evalPureBuiltinViaEvmYulLean_calldatasize (args : List Nat) : @@ -2792,7 +2794,7 @@ values. This works because: 1. The `.evmYulLean` backend routes through `evalBuiltinCallViaEvmYulLean`, which ignores all context and delegates to `evalPureBuiltinViaEvmYulLean`. -2. Pure builtins in `evalBuiltinCallWithContext` only use `argVals`. +2. Pure builtins in `legacyEvalBuiltinCallWithContext` only use `argVals`. These are the key composition lemmas for Phase 4 (retargeting the theorem stack to EVMYulLean). -/ @@ -2802,275 +2804,275 @@ stack to EVMYulLean). -/ (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "add" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "add" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_add_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_sub_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "sub" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "sub" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_sub_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_mul_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "mul" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "mul" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_mul_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_div_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "div" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "div" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_div_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_mod_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "mod" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "mod" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_mod_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_eq_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "eq" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "eq" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_eq_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_iszero_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "iszero" [a] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "iszero" [a] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_iszero_bridge storage sender selector calldata a] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_lt_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "lt" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "lt" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_lt_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_gt_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "gt" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "gt" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_gt_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_slt_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "slt" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "slt" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_slt_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_sgt_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "sgt" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "sgt" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_sgt_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_and_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "and" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "and" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_and_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_or_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "or" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "or" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_or_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_xor_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "xor" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "xor" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_xor_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_not_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "not" [a] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "not" [a] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_not_bridge storage sender selector calldata a] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_shl_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "shl" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "shl" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_shl_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_shr_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "shr" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "shr" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_shr_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_addmod_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b c : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "addmod" [a, b, c] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "addmod" [a, b, c] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_addmod_bridge storage sender selector calldata a b c] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_mulmod_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b c : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "mulmod" [a, b, c] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "mulmod" [a, b, c] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_mulmod_bridge storage sender selector calldata a b c] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_byte_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (i x : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "byte" [i, x] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "byte" [i, x] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_byte_bridge storage sender selector calldata i x] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_exp_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "exp" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "exp" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_exp_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_sdiv_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "sdiv" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "sdiv" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_sdiv_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_smod_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (a b : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "smod" [a, b] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "smod" [a, b] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_smod_bridge storage sender selector calldata a b] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_sar_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (shift value : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "sar" [shift, value] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "sar" [shift, value] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_sar_bridge storage sender selector calldata shift value] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_signextend_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (byteIdx value : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "signextend" [byteIdx, value] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "signextend" [byteIdx, value] := by - simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallViaEvmYulLean] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, evalBuiltinCallViaEvmYulLean] rw [← evalBuiltinCall_signextend_bridge storage sender selector calldata byteIdx value] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] /-! ## Context-Aware Backend Routing Surface @@ -3094,108 +3096,108 @@ can rewrite against. -/ (calldata : List Nat) (slot : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "sload" [slot] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "sload" [slot] := by - simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_caller_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "caller" [] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "caller" [] := by - simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext] + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_address_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "address" [] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "address" [] := by - simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext] + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_callvalue_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "callvalue" [] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "callvalue" [] := by - simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext] + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_timestamp_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "timestamp" [] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "timestamp" [] := by - simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext] + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_number_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "number" [] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "number" [] := by - simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext] + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_blobbasefee_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "blobbasefee" [] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "blobbasefee" [] := by - simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext] + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_chainid_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "chainid" [] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "chainid" [] := by - simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext] + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_calldataload_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (offset : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "calldataload" [offset] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "calldataload" [offset] := by - simp only [evalBuiltinCallWithBackendContext] + simp only [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext] rw [← evalBuiltinCall_calldataload_bridge storage sender selector calldata offset] - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCall, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_calldatasize_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "calldatasize" [] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "calldatasize" [] := by - simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext] + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext] @[simp] theorem evalBuiltinCallWithBackendContext_evmYulLean_mappingSlot_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (base key : Nat) : evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "mappingSlot" [base, key] = - evalBuiltinCallWithContext storage sender msgValue thisAddress + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "mappingSlot" [base, key] := by - simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] /-! ## Composite Backend Equivalence Theorem This is the key Phase 4 composition lemma. For any pure builtin `func` in the set of 25 universally-bridged builtins (all fully proven), all with context-lifted bridge theorems, the EVMYulLean backend agrees with the Verity backend -(represented by `evalBuiltinCallWithContext`). +(represented by `legacyEvalBuiltinCallWithContext`). The theorem is structured as a disjunction: either `func` matches one of the 25 bridged pure builtins (and the backends agree), or `func` is a state-dependent @@ -3214,7 +3216,7 @@ separately when the builtin is known to be in the bridged pure fragment. -/ This theorem applies away from the directly handled context/env builtins; per-builtin bridge lemmas are applied after this routing rewrite when the builtin is known to lie in the bridged pure fragment. -/ -theorem evalBuiltinCallWithBackendContext_evmYulLean_pure_bridge +private theorem evalBuiltinCallWithBackendContext_evmYulLean_pure_bridge (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (func : String) (argVals : List Nat) (hCaller : func ≠ "caller") @@ -3228,7 +3230,7 @@ theorem evalBuiltinCallWithBackendContext_evmYulLean_pure_bridge evalBuiltinCallWithBackendContext .evmYulLean storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata func argVals = evalBuiltinCallViaEvmYulLean storage sender selector calldata func argVals := by - simp [evalBuiltinCallWithBackendContext, hCaller, hAddress, hCallvalue, hTimestamp, hNumber, + simp [evalBuiltinCallWithBackendContext, evalBuiltinCallWithEvmYulLeanContext, hCaller, hAddress, hCallvalue, hTimestamp, hNumber, hChainid, hBlobbasefee, hCalldatasize] /-! ## Phase 4 Backend Equivalence Surface @@ -3257,31 +3259,6 @@ will invoke. | **Total bridged** | **36** | **36 proven, 0 sorry** | -/ -/-- The set of builtins for which the `.evmYulLean` and `.verity` backends - produce identical results. This now covers all 36 builtins handled by - `evalBuiltinCallWithContext`, including `mappingSlot` which is bridged - via the shared keccak-faithful `abstractMappingSlot` derivation. - - Phase 4's `Preservation.lean` retargeting uses this set to determine - which builtin invocations can be transparently switched from `.verity` - to `.evmYulLean` backend without affecting the proof. -/ -def bridgedBuiltins : List String := - ["add", "sub", "mul", "div", "mod", - "lt", "gt", "eq", "iszero", - "and", "or", "xor", "not", "shl", "shr", - "addmod", "mulmod", "byte", - "slt", "sgt", - "exp", "sdiv", "smod", "sar", "signextend", - "caller", "address", "callvalue", "timestamp", - "number", "chainid", "blobbasefee", - "calldataload", "calldatasize", - "sload", "mappingSlot"] - -/-- The set of builtins that the `.evmYulLean` backend cannot handle is - now empty: every builtin in `evalBuiltinCallWithContext` has a bridge - lemma and appears in `bridgedBuiltins`. -/ -def unbridgedBuiltins : List String := [] - /-! ## Remaining Core Equivalence Proofs — Status All 25 pure builtins now have universal bridge theorems diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgePredicates.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgePredicates.lean new file mode 100644 index 000000000..e7f6b718b --- /dev/null +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgePredicates.lean @@ -0,0 +1,847 @@ +/- + Neutral EVMYulLean bridge-fragment predicates. + + This module contains only the syntactic builtin set and `Bridged*` Yul + fragment predicates used by native closure proofs. It deliberately avoids the + transition-only oracle and executor equivalence stack. +-/ + +import Compiler.Yul.Ast +import Compiler.Proofs.YulGeneration.LogNames + +namespace Compiler.Proofs.YulGeneration.Backends + +/-- Builtin names accepted by the current native generated-fragment closure + predicate. Kept here so native closure proofs can name the supported + fragment without importing transition-only executor equivalence proofs. -/ +def bridgedBuiltins : List String := + ["add", "sub", "mul", "div", "mod", + "lt", "gt", "eq", "iszero", + "and", "or", "xor", "not", "shl", "shr", + "addmod", "mulmod", "byte", + "slt", "sgt", + "exp", "sdiv", "smod", "sar", "signextend", + "caller", "address", "callvalue", "timestamp", + "number", "chainid", "blobbasefee", + "calldataload", "calldatasize", + "sload", "mappingSlot"] + +/-- Builtin names intentionally excluded from the current native generated + fragment. The list is empty for the fragment tracked in this module. -/ +def unbridgedBuiltins : List String := [] + +def allowedExprCallName (func : String) : Prop := + func ∈ bridgedBuiltins ∨ func = "tload" ∨ func = "mload" ∨ func = "keccak256" + +inductive BridgedExpr : Compiler.Yul.YulExpr → Prop + | lit (n : Nat) : BridgedExpr (.lit n) + | hex (n : Nat) : BridgedExpr (.hex n) + | str (s : String) : BridgedExpr (.str s) + | ident (name : String) : BridgedExpr (.ident name) + | call (func : String) (args : List Compiler.Yul.YulExpr) + (hName : allowedExprCallName func) + (hArgs : ∀ arg ∈ args, BridgedExpr arg) : + BridgedExpr (.call func args) + +inductive BridgedStraightStmt : Compiler.Yul.YulStmt → Prop + | comment (text : String) : BridgedStraightStmt (.comment text) + | let_ (name : String) (value : Compiler.Yul.YulExpr) + (hValue : BridgedExpr value) : + BridgedStraightStmt (.let_ name value) + | letMany (names : List String) (value : Compiler.Yul.YulExpr) : + BridgedStraightStmt (.letMany names value) + | assign (name : String) (value : Compiler.Yul.YulExpr) + (hValue : BridgedExpr value) : + BridgedStraightStmt (.assign name value) + | leave : BridgedStraightStmt .leave + | expr_sstore_mapping (baseExpr keyExpr valExpr : Compiler.Yul.YulExpr) + (hBase : BridgedExpr baseExpr) (hKey : BridgedExpr keyExpr) + (hVal : BridgedExpr valExpr) : + BridgedStraightStmt + (.expr (.call "sstore" [.call "mappingSlot" [baseExpr, keyExpr], valExpr])) + | expr_sstore_lit (slot : Nat) (valExpr : Compiler.Yul.YulExpr) + (hVal : BridgedExpr valExpr) : + BridgedStraightStmt (.expr (.call "sstore" [.lit slot, valExpr])) + | expr_sstore_ident (slotName : String) (valExpr : Compiler.Yul.YulExpr) + (hVal : BridgedExpr valExpr) : + BridgedStraightStmt (.expr (.call "sstore" [.ident slotName, valExpr])) + | expr_sstore_add (leftExpr rightExpr valExpr : Compiler.Yul.YulExpr) + (hLeft : BridgedExpr leftExpr) (hRight : BridgedExpr rightExpr) + (hVal : BridgedExpr valExpr) : + BridgedStraightStmt + (.expr (.call "sstore" [.call "add" [leftExpr, rightExpr], valExpr])) + | expr_mstore (offsetExpr valExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : + BridgedStraightStmt (.expr (.call "mstore" [offsetExpr, valExpr])) + | expr_tstore (offsetExpr valExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : + BridgedStraightStmt (.expr (.call "tstore" [offsetExpr, valExpr])) + | expr_stop : BridgedStraightStmt (.expr (.call "stop" [])) + | expr_return (offsetExpr sizeExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : + BridgedStraightStmt (.expr (.call "return" [offsetExpr, sizeExpr])) + | expr_revert (offsetExpr sizeExpr : Compiler.Yul.YulExpr) : + BridgedStraightStmt (.expr (.call "revert" [offsetExpr, sizeExpr])) + | expr_log (func : String) (args : List Compiler.Yul.YulExpr) + (hLog : isYulLogName func = true) + (hArgs : ∀ arg ∈ args, BridgedExpr arg) : + BridgedStraightStmt (.expr (.call func args)) + | funcDef (name : String) (params rets : List String) + (body : List Compiler.Yul.YulStmt) : + BridgedStraightStmt (.funcDef name params rets body) + +def BridgedStraightStmts (stmts : List Compiler.Yul.YulStmt) : Prop := + ∀ stmt ∈ stmts, BridgedStraightStmt stmt + +theorem BridgedStraightStmts_nil : BridgedStraightStmts [] := by + intro stmt hMem + cases hMem + +theorem BridgedStraightStmts_cons {stmt : Compiler.Yul.YulStmt} + {stmts : List Compiler.Yul.YulStmt} + (hStmt : BridgedStraightStmt stmt) (hStmts : BridgedStraightStmts stmts) : + BridgedStraightStmts (stmt :: stmts) := by + intro s hMem + cases hMem with + | head => exact hStmt + | tail _ hTail => exact hStmts s hTail + +theorem BridgedStraightStmts_append {xs ys : List Compiler.Yul.YulStmt} + (hXs : BridgedStraightStmts xs) (hYs : BridgedStraightStmts ys) : + BridgedStraightStmts (xs ++ ys) := by + intro stmt hMem + simp only [List.mem_append] at hMem + cases hMem with + | inl h => exact hXs stmt h + | inr h => exact hYs stmt h + +theorem BridgedStraightStmts_singleton {stmt : Compiler.Yul.YulStmt} + (hStmt : BridgedStraightStmt stmt) : BridgedStraightStmts [stmt] := + BridgedStraightStmts_cons hStmt BridgedStraightStmts_nil + +theorem BridgedStraightStmts_snoc {xs : List Compiler.Yul.YulStmt} + {y : Compiler.Yul.YulStmt} + (hXs : BridgedStraightStmts xs) (hY : BridgedStraightStmt y) : + BridgedStraightStmts (xs ++ [y]) := + BridgedStraightStmts_append hXs (BridgedStraightStmts_singleton hY) + +theorem BridgedStraightStmts_map_mstore + (pairs : List (Compiler.Yul.YulExpr × Compiler.Yul.YulExpr)) + (hPairs : ∀ p ∈ pairs, BridgedExpr p.1 ∧ BridgedExpr p.2) : + BridgedStraightStmts + (pairs.map fun p => + Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "mstore" [p.1, p.2])) := by + induction pairs with + | nil => exact BridgedStraightStmts_nil + | cons p rest ih => + have hHead : BridgedExpr p.1 ∧ BridgedExpr p.2 := hPairs p (by simp) + have hRest : ∀ q ∈ rest, BridgedExpr q.1 ∧ BridgedExpr q.2 := by + intro q hq + exact hPairs q (by simp [hq]) + exact BridgedStraightStmts_cons + (BridgedStraightStmt.expr_mstore p.1 p.2 hHead.1 hHead.2) + (ih hRest) + +theorem BridgedStraightStmts_map_tstore + (pairs : List (Compiler.Yul.YulExpr × Compiler.Yul.YulExpr)) + (hPairs : ∀ p ∈ pairs, BridgedExpr p.1 ∧ BridgedExpr p.2) : + BridgedStraightStmts + (pairs.map fun p => + Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "tstore" [p.1, p.2])) := by + induction pairs with + | nil => exact BridgedStraightStmts_nil + | cons p rest ih => + have hHead : BridgedExpr p.1 ∧ BridgedExpr p.2 := hPairs p (by simp) + have hRest : ∀ q ∈ rest, BridgedExpr q.1 ∧ BridgedExpr q.2 := by + intro q hq + exact hPairs q (by simp [hq]) + exact BridgedStraightStmts_cons + (BridgedStraightStmt.expr_tstore p.1 p.2 hHead.1 hHead.2) + (ih hRest) + +def BridgedSwitchCases (cases : List (Nat × List Compiler.Yul.YulStmt)) : Prop := + ∀ scrutinee value body, + cases.find? (fun x => decide (x.fst = scrutinee)) = some (value, body) → + BridgedStraightStmts body + +inductive BridgedStmt : Compiler.Yul.YulStmt → Prop + | straight (stmt : Compiler.Yul.YulStmt) + (hStmt : BridgedStraightStmt stmt) : + BridgedStmt stmt + | block (stmts : List Compiler.Yul.YulStmt) + (hStmts : ∀ stmt ∈ stmts, BridgedStmt stmt) : + BridgedStmt (.block stmts) + | if_ (cond : Compiler.Yul.YulExpr) (body : List Compiler.Yul.YulStmt) + (hCond : BridgedExpr cond) + (hBody : ∀ stmt ∈ body, BridgedStmt stmt) : + BridgedStmt (.if_ cond body) + | «switch» (expr : Compiler.Yul.YulExpr) + (cases : List (Nat × List Compiler.Yul.YulStmt)) + (defaultCase : Option (List Compiler.Yul.YulStmt)) + (hExpr : BridgedExpr expr) + (hCases : ∀ scrutinee value body, + cases.find? (fun x => decide (x.fst = scrutinee)) = some (value, body) → + ∀ stmt ∈ body, BridgedStmt stmt) + (hDefault : ∀ body, defaultCase = some body → + ∀ stmt ∈ body, BridgedStmt stmt) : + BridgedStmt (.switch expr cases defaultCase) + | for_ (init : List Compiler.Yul.YulStmt) (cond : Compiler.Yul.YulExpr) + (post body : List Compiler.Yul.YulStmt) + (hInit : ∀ stmt ∈ init, BridgedStmt stmt) + (hCond : BridgedExpr cond) + (hPost : ∀ stmt ∈ post, BridgedStmt stmt) + (hBody : ∀ stmt ∈ body, BridgedStmt stmt) : + BridgedStmt (.for_ init cond post body) + +def BridgedStmts (stmts : List Compiler.Yul.YulStmt) : Prop := + ∀ stmt ∈ stmts, BridgedStmt stmt + +theorem BridgedStmts_nil : BridgedStmts [] := by + intro stmt hMem + cases hMem + +theorem BridgedStmts_cons {stmt : Compiler.Yul.YulStmt} + {stmts : List Compiler.Yul.YulStmt} + (hStmt : BridgedStmt stmt) (hStmts : BridgedStmts stmts) : + BridgedStmts (stmt :: stmts) := by + intro s hMem + cases hMem with + | head => exact hStmt + | tail _ hTail => exact hStmts s hTail + +theorem BridgedStmts_append {xs ys : List Compiler.Yul.YulStmt} + (hXs : BridgedStmts xs) (hYs : BridgedStmts ys) : + BridgedStmts (xs ++ ys) := by + intro stmt hMem + simp only [List.mem_append] at hMem + cases hMem with + | inl h => exact hXs stmt h + | inr h => exact hYs stmt h + +theorem BridgedStmts_singleton {stmt : Compiler.Yul.YulStmt} + (hStmt : BridgedStmt stmt) : BridgedStmts [stmt] := + BridgedStmts_cons hStmt BridgedStmts_nil + +theorem BridgedStmts_snoc {xs : List Compiler.Yul.YulStmt} + {y : Compiler.Yul.YulStmt} + (hXs : BridgedStmts xs) (hY : BridgedStmt y) : + BridgedStmts (xs ++ [y]) := + BridgedStmts_append hXs (BridgedStmts_singleton hY) + +theorem bridgedExpr_keccak256 (offsetExpr sizeExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : + BridgedExpr + (Compiler.Yul.YulExpr.call "keccak256" [offsetExpr, sizeExpr]) := by + refine BridgedExpr.call "keccak256" _ (Or.inr (Or.inr (Or.inr rfl))) ?_ + intro arg hMem + simp only [List.mem_cons, List.mem_nil_iff, or_false] at hMem + rcases hMem with rfl | rfl + · exact hOffset + · exact hSize + +theorem bridgedExpr_mload (offsetExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) : + BridgedExpr + (Compiler.Yul.YulExpr.call "mload" [offsetExpr]) := by + refine BridgedExpr.call "mload" _ (Or.inr (Or.inr (Or.inl rfl))) ?_ + intro arg hMem + simp only [List.mem_singleton] at hMem + subst hMem + exact hOffset + +theorem bridgedExpr_tload (slotExpr : Compiler.Yul.YulExpr) + (hSlot : BridgedExpr slotExpr) : + BridgedExpr + (Compiler.Yul.YulExpr.call "tload" [slotExpr]) := by + refine BridgedExpr.call "tload" _ (Or.inr (Or.inl rfl)) ?_ + intro arg hMem + simp only [List.mem_singleton] at hMem + subst hMem + exact hSlot + +theorem bridgedStraightStmt_let_mload (name : String) + (offsetExpr : Compiler.Yul.YulExpr) (hOffset : BridgedExpr offsetExpr) : + BridgedStraightStmt + (.let_ name (Compiler.Yul.YulExpr.call "mload" [offsetExpr])) := + BridgedStraightStmt.let_ name _ (bridgedExpr_mload offsetExpr hOffset) + +theorem bridgedStraightStmt_let_tload (name : String) + (slotExpr : Compiler.Yul.YulExpr) (hSlot : BridgedExpr slotExpr) : + BridgedStraightStmt + (.let_ name (Compiler.Yul.YulExpr.call "tload" [slotExpr])) := + BridgedStraightStmt.let_ name _ (bridgedExpr_tload slotExpr hSlot) + +theorem bridgedStraightStmt_let_keccak256 (name : String) + (offsetExpr sizeExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : + BridgedStraightStmt + (.let_ name + (Compiler.Yul.YulExpr.call "keccak256" [offsetExpr, sizeExpr])) := + BridgedStraightStmt.let_ name _ + (bridgedExpr_keccak256 offsetExpr sizeExpr hOffset hSize) + +theorem bridgedStraightStmt_assign_mload (name : String) + (offsetExpr : Compiler.Yul.YulExpr) (hOffset : BridgedExpr offsetExpr) : + BridgedStraightStmt + (.assign name (Compiler.Yul.YulExpr.call "mload" [offsetExpr])) := + BridgedStraightStmt.assign name _ (bridgedExpr_mload offsetExpr hOffset) + +theorem bridgedStraightStmt_assign_tload (name : String) + (slotExpr : Compiler.Yul.YulExpr) (hSlot : BridgedExpr slotExpr) : + BridgedStraightStmt + (.assign name (Compiler.Yul.YulExpr.call "tload" [slotExpr])) := + BridgedStraightStmt.assign name _ (bridgedExpr_tload slotExpr hSlot) + +theorem bridgedStraightStmt_assign_keccak256 (name : String) + (offsetExpr sizeExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : + BridgedStraightStmt + (.assign name + (Compiler.Yul.YulExpr.call "keccak256" [offsetExpr, sizeExpr])) := + BridgedStraightStmt.assign name _ + (bridgedExpr_keccak256 offsetExpr sizeExpr hOffset hSize) + +theorem bridgedStraightStmt_log_of_bridged_args + (func : String) (args : List Compiler.Yul.YulExpr) + (hLog : isYulLogName func = true) + (hArgs : ∀ arg ∈ args, BridgedExpr arg) : + BridgedStraightStmt (.expr (.call func args)) := + BridgedStraightStmt.expr_log func args hLog hArgs + +theorem bridgedStmt_of_bridgedStraightStmt {stmt : Compiler.Yul.YulStmt} + (hStmt : BridgedStraightStmt stmt) : BridgedStmt stmt := + BridgedStmt.straight stmt hStmt + +theorem bridgedStmt_log_of_bridged_args + (func : String) (args : List Compiler.Yul.YulExpr) + (hLog : isYulLogName func = true) + (hArgs : ∀ arg ∈ args, BridgedExpr arg) : + BridgedStmt (.expr (.call func args)) := + bridgedStmt_of_bridgedStraightStmt + (bridgedStraightStmt_log_of_bridged_args func args hLog hArgs) + +theorem bridgedStmt_let_mload (name : String) + (offsetExpr : Compiler.Yul.YulExpr) (hOffset : BridgedExpr offsetExpr) : + BridgedStmt (.let_ name (Compiler.Yul.YulExpr.call "mload" [offsetExpr])) := + bridgedStmt_of_bridgedStraightStmt + (bridgedStraightStmt_let_mload name offsetExpr hOffset) + +theorem bridgedStmt_let_tload (name : String) + (slotExpr : Compiler.Yul.YulExpr) (hSlot : BridgedExpr slotExpr) : + BridgedStmt (.let_ name (Compiler.Yul.YulExpr.call "tload" [slotExpr])) := + bridgedStmt_of_bridgedStraightStmt + (bridgedStraightStmt_let_tload name slotExpr hSlot) + +theorem bridgedStmt_let_keccak256 (name : String) + (offsetExpr sizeExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : + BridgedStmt + (.let_ name + (Compiler.Yul.YulExpr.call "keccak256" [offsetExpr, sizeExpr])) := + bridgedStmt_of_bridgedStraightStmt + (bridgedStraightStmt_let_keccak256 name offsetExpr sizeExpr hOffset hSize) + +theorem bridgedStmt_assign_mload (name : String) + (offsetExpr : Compiler.Yul.YulExpr) (hOffset : BridgedExpr offsetExpr) : + BridgedStmt + (.assign name (Compiler.Yul.YulExpr.call "mload" [offsetExpr])) := + bridgedStmt_of_bridgedStraightStmt + (bridgedStraightStmt_assign_mload name offsetExpr hOffset) + +theorem bridgedStmt_assign_tload (name : String) + (slotExpr : Compiler.Yul.YulExpr) (hSlot : BridgedExpr slotExpr) : + BridgedStmt + (.assign name (Compiler.Yul.YulExpr.call "tload" [slotExpr])) := + bridgedStmt_of_bridgedStraightStmt + (bridgedStraightStmt_assign_tload name slotExpr hSlot) + +theorem bridgedStmt_assign_keccak256 (name : String) + (offsetExpr sizeExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : + BridgedStmt + (.assign name + (Compiler.Yul.YulExpr.call "keccak256" [offsetExpr, sizeExpr])) := + bridgedStmt_of_bridgedStraightStmt + (bridgedStraightStmt_assign_keccak256 name offsetExpr sizeExpr hOffset hSize) + +theorem bridgedStmt_mstore_of_bridged_args + (offsetExpr valExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : + BridgedStmt + (.expr (Compiler.Yul.YulExpr.call "mstore" [offsetExpr, valExpr])) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.expr_mstore offsetExpr valExpr hOffset hVal) + +theorem bridgedStmt_tstore_of_bridged_args + (offsetExpr valExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : + BridgedStmt + (.expr (Compiler.Yul.YulExpr.call "tstore" [offsetExpr, valExpr])) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.expr_tstore offsetExpr valExpr hOffset hVal) + +theorem bridgedStmt_sstore_mapping_of_bridged_args + (baseExpr keyExpr valExpr : Compiler.Yul.YulExpr) + (hBase : BridgedExpr baseExpr) (hKey : BridgedExpr keyExpr) + (hVal : BridgedExpr valExpr) : + BridgedStmt + (.expr (Compiler.Yul.YulExpr.call "sstore" + [Compiler.Yul.YulExpr.call "mappingSlot" [baseExpr, keyExpr], valExpr])) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.expr_sstore_mapping baseExpr keyExpr valExpr hBase hKey hVal) + +theorem bridgedStmt_sstore_lit_of_bridged_val + (slot : Nat) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) : + BridgedStmt + (.expr (Compiler.Yul.YulExpr.call "sstore" [.lit slot, valExpr])) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.expr_sstore_lit slot valExpr hVal) + +theorem bridgedStmt_sstore_ident_of_bridged_val + (slotName : String) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) : + BridgedStmt + (.expr (Compiler.Yul.YulExpr.call "sstore" [.ident slotName, valExpr])) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.expr_sstore_ident slotName valExpr hVal) + +theorem bridgedStmt_sstore_add_of_bridged_args + (leftExpr rightExpr valExpr : Compiler.Yul.YulExpr) + (hLeft : BridgedExpr leftExpr) (hRight : BridgedExpr rightExpr) + (hVal : BridgedExpr valExpr) : + BridgedStmt + (.expr (Compiler.Yul.YulExpr.call "sstore" + [Compiler.Yul.YulExpr.call "add" [leftExpr, rightExpr], valExpr])) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.expr_sstore_add leftExpr rightExpr valExpr hLeft hRight hVal) + +theorem bridgedStmt_stop : + BridgedStmt (Compiler.Yul.YulStmt.expr (Compiler.Yul.YulExpr.call "stop" [])) := + bridgedStmt_of_bridgedStraightStmt BridgedStraightStmt.expr_stop + +theorem bridgedStmt_return_of_bridged_args + (offsetExpr sizeExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : + BridgedStmt + (.expr (Compiler.Yul.YulExpr.call "return" [offsetExpr, sizeExpr])) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.expr_return offsetExpr sizeExpr hOffset hSize) + +theorem bridgedStmt_revert (offsetExpr sizeExpr : Compiler.Yul.YulExpr) : + BridgedStmt + (.expr (Compiler.Yul.YulExpr.call "revert" [offsetExpr, sizeExpr])) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.expr_revert offsetExpr sizeExpr) + +theorem bridgedStmt_leave : BridgedStmt .leave := + bridgedStmt_of_bridgedStraightStmt BridgedStraightStmt.leave + +theorem bridgedStmt_let_of_bridged_val + (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) : + BridgedStmt (.let_ name value) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.let_ name value hValue) + +theorem bridgedStmt_letMany (names : List String) (value : Compiler.Yul.YulExpr) : + BridgedStmt (.letMany names value) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.letMany names value) + +theorem bridgedStmt_assign_of_bridged_val + (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) : + BridgedStmt (.assign name value) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.assign name value hValue) + +theorem bridgedStmt_comment (text : String) : + BridgedStmt (.comment text) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.comment text) + +theorem bridgedStmt_funcDef + (name : String) (params rets : List String) + (body : List Compiler.Yul.YulStmt) : + BridgedStmt (.funcDef name params rets body) := + bridgedStmt_of_bridgedStraightStmt + (BridgedStraightStmt.funcDef name params rets body) + +theorem BridgedStmts_of_BridgedStraightStmts + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStraightStmts stmts) : + BridgedStmts stmts := by + intro stmt hMem + exact bridgedStmt_of_bridgedStraightStmt (hStmts stmt hMem) + +theorem BridgedStmts_cons_straight {stmt : Compiler.Yul.YulStmt} + {stmts : List Compiler.Yul.YulStmt} + (hStmt : BridgedStraightStmt stmt) (hStmts : BridgedStmts stmts) : + BridgedStmts (stmt :: stmts) := + BridgedStmts_cons (bridgedStmt_of_bridgedStraightStmt hStmt) hStmts + +theorem BridgedStmts_singleton_straight {stmt : Compiler.Yul.YulStmt} + (hStmt : BridgedStraightStmt stmt) : + BridgedStmts [stmt] := + BridgedStmts_singleton (bridgedStmt_of_bridgedStraightStmt hStmt) + +theorem BridgedStmts_append_straight {xs ys : List Compiler.Yul.YulStmt} + (hXs : BridgedStraightStmts xs) (hYs : BridgedStmts ys) : + BridgedStmts (xs ++ ys) := + BridgedStmts_append (BridgedStmts_of_BridgedStraightStmts hXs) hYs + +theorem BridgedStmts_map_mstore + (pairs : List (Compiler.Yul.YulExpr × Compiler.Yul.YulExpr)) + (hPairs : ∀ p ∈ pairs, BridgedExpr p.1 ∧ BridgedExpr p.2) : + BridgedStmts + (pairs.map fun p => + Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "mstore" [p.1, p.2])) := + BridgedStmts_of_BridgedStraightStmts + (BridgedStraightStmts_map_mstore pairs hPairs) + +theorem bridgedStmt_block_of_bridgedStmts + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmt (.block stmts) := + BridgedStmt.block stmts hStmts + +theorem BridgedStmts_singleton_block + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts [.block stmts] := + BridgedStmts_singleton (bridgedStmt_block_of_bridgedStmts hStmts) + +theorem BridgedStmts_cons_block + {blockStmts stmts : List Compiler.Yul.YulStmt} + (hBlock : BridgedStmts blockStmts) (hStmts : BridgedStmts stmts) : + BridgedStmts (.block blockStmts :: stmts) := + BridgedStmts_cons (bridgedStmt_block_of_bridgedStmts hBlock) hStmts + +theorem bridgedStmt_if_of_bridgedStmts + {cond : Compiler.Yul.YulExpr} {body : List Compiler.Yul.YulStmt} + (hCond : BridgedExpr cond) (hBody : BridgedStmts body) : + BridgedStmt (.if_ cond body) := + BridgedStmt.if_ cond body hCond hBody + +theorem BridgedStmts_singleton_if + {cond : Compiler.Yul.YulExpr} {body : List Compiler.Yul.YulStmt} + (hCond : BridgedExpr cond) (hBody : BridgedStmts body) : + BridgedStmts [.if_ cond body] := + BridgedStmts_singleton (bridgedStmt_if_of_bridgedStmts hCond hBody) + +theorem BridgedStmts_cons_if + {cond : Compiler.Yul.YulExpr} {body stmts : List Compiler.Yul.YulStmt} + (hCond : BridgedExpr cond) (hBody : BridgedStmts body) + (hStmts : BridgedStmts stmts) : + BridgedStmts (.if_ cond body :: stmts) := + BridgedStmts_cons (bridgedStmt_if_of_bridgedStmts hCond hBody) hStmts + +theorem bridgedStmt_for_of_bridgedStmts + {init : List Compiler.Yul.YulStmt} {cond : Compiler.Yul.YulExpr} + {post body : List Compiler.Yul.YulStmt} + (hInit : BridgedStmts init) (hCond : BridgedExpr cond) + (hPost : BridgedStmts post) (hBody : BridgedStmts body) : + BridgedStmt (.for_ init cond post body) := + BridgedStmt.for_ init cond post body hInit hCond hPost hBody + +theorem BridgedStmts_singleton_for + {init : List Compiler.Yul.YulStmt} {cond : Compiler.Yul.YulExpr} + {post body : List Compiler.Yul.YulStmt} + (hInit : BridgedStmts init) (hCond : BridgedExpr cond) + (hPost : BridgedStmts post) (hBody : BridgedStmts body) : + BridgedStmts [.for_ init cond post body] := + BridgedStmts_singleton + (bridgedStmt_for_of_bridgedStmts hInit hCond hPost hBody) + +theorem BridgedStmts_cons_for + {init : List Compiler.Yul.YulStmt} {cond : Compiler.Yul.YulExpr} + {post body stmts : List Compiler.Yul.YulStmt} + (hInit : BridgedStmts init) (hCond : BridgedExpr cond) + (hPost : BridgedStmts post) (hBody : BridgedStmts body) + (hStmts : BridgedStmts stmts) : + BridgedStmts (.for_ init cond post body :: stmts) := + BridgedStmts_cons + (bridgedStmt_for_of_bridgedStmts hInit hCond hPost hBody) hStmts + +theorem bridgedStmt_switch_of_bridgedStmts + {expr : Compiler.Yul.YulExpr} + {cases : List (Nat × List Compiler.Yul.YulStmt)} + {defaultCase : Option (List Compiler.Yul.YulStmt)} + (hExpr : BridgedExpr expr) + (hCases : ∀ scrutinee value body, + cases.find? (fun x => decide (x.fst = scrutinee)) = some (value, body) → + BridgedStmts body) + (hDefault : ∀ body, defaultCase = some body → BridgedStmts body) : + BridgedStmt (.switch expr cases defaultCase) := + BridgedStmt.switch expr cases defaultCase hExpr hCases hDefault + +theorem BridgedStmts_singleton_switch + {expr : Compiler.Yul.YulExpr} + {cases : List (Nat × List Compiler.Yul.YulStmt)} + {defaultCase : Option (List Compiler.Yul.YulStmt)} + (hExpr : BridgedExpr expr) + (hCases : ∀ scrutinee value body, + cases.find? (fun x => decide (x.fst = scrutinee)) = some (value, body) → + BridgedStmts body) + (hDefault : ∀ body, defaultCase = some body → BridgedStmts body) : + BridgedStmts [.switch expr cases defaultCase] := + BridgedStmts_singleton + (bridgedStmt_switch_of_bridgedStmts hExpr hCases hDefault) + +theorem BridgedStmts_cons_switch + {expr : Compiler.Yul.YulExpr} + {cases : List (Nat × List Compiler.Yul.YulStmt)} + {defaultCase : Option (List Compiler.Yul.YulStmt)} + {stmts : List Compiler.Yul.YulStmt} + (hExpr : BridgedExpr expr) + (hCases : ∀ scrutinee value body, + cases.find? (fun x => decide (x.fst = scrutinee)) = some (value, body) → + BridgedStmts body) + (hDefault : ∀ body, defaultCase = some body → BridgedStmts body) + (hStmts : BridgedStmts stmts) : + BridgedStmts (.switch expr cases defaultCase :: stmts) := + BridgedStmts_cons + (bridgedStmt_switch_of_bridgedStmts hExpr hCases hDefault) hStmts + +theorem bridgedStmt_block_of_bridgedStraightStmts + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStraightStmts stmts) : + BridgedStmt (.block stmts) := + bridgedStmt_block_of_bridgedStmts + (BridgedStmts_of_BridgedStraightStmts hStmts) + +theorem bridgedStmt_if_of_bridgedStraightStmts + {cond : Compiler.Yul.YulExpr} {body : List Compiler.Yul.YulStmt} + (hCond : BridgedExpr cond) (hBody : BridgedStraightStmts body) : + BridgedStmt (.if_ cond body) := + bridgedStmt_if_of_bridgedStmts hCond + (BridgedStmts_of_BridgedStraightStmts hBody) + +theorem bridgedStmt_for_of_bridgedStraightStmts + {init : List Compiler.Yul.YulStmt} {cond : Compiler.Yul.YulExpr} + {post body : List Compiler.Yul.YulStmt} + (hInit : BridgedStraightStmts init) (hCond : BridgedExpr cond) + (hPost : BridgedStraightStmts post) (hBody : BridgedStraightStmts body) : + BridgedStmt (.for_ init cond post body) := + bridgedStmt_for_of_bridgedStmts + (BridgedStmts_of_BridgedStraightStmts hInit) hCond + (BridgedStmts_of_BridgedStraightStmts hPost) + (BridgedStmts_of_BridgedStraightStmts hBody) + +theorem BridgedStmts_map_tstore + (pairs : List (Compiler.Yul.YulExpr × Compiler.Yul.YulExpr)) + (hPairs : ∀ p ∈ pairs, BridgedExpr p.1 ∧ BridgedExpr p.2) : + BridgedStmts + (pairs.map fun p => + Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "tstore" [p.1, p.2])) := + BridgedStmts_of_BridgedStraightStmts + (BridgedStraightStmts_map_tstore pairs hPairs) + +theorem bridgedStmt_revert_zero : + BridgedStmt + (Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "revert" + [Compiler.Yul.YulExpr.lit 0, Compiler.Yul.YulExpr.lit 0])) := + bridgedStmt_revert (Compiler.Yul.YulExpr.lit 0) (Compiler.Yul.YulExpr.lit 0) + +theorem BridgedStmts_singleton_revert_zero : + BridgedStmts + [Compiler.Yul.YulStmt.expr + (Compiler.Yul.YulExpr.call "revert" + [Compiler.Yul.YulExpr.lit 0, Compiler.Yul.YulExpr.lit 0])] := + BridgedStmts_singleton bridgedStmt_revert_zero + +theorem BridgedStmts_singleton_comment (text : String) : + BridgedStmts [.comment text] := + BridgedStmts_singleton (bridgedStmt_comment text) + +theorem BridgedStmts_cons_comment + (text : String) {stmts : List Compiler.Yul.YulStmt} + (hStmts : BridgedStmts stmts) : + BridgedStmts (.comment text :: stmts) := + BridgedStmts_cons (bridgedStmt_comment text) hStmts + +theorem BridgedStmts_singleton_let + (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) : + BridgedStmts [.let_ name value] := + BridgedStmts_singleton (bridgedStmt_let_of_bridged_val name value hValue) + +theorem BridgedStmts_cons_let + (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts (.let_ name value :: stmts) := + BridgedStmts_cons (bridgedStmt_let_of_bridged_val name value hValue) hStmts + +theorem BridgedStmts_singleton_assign + (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) : + BridgedStmts [.assign name value] := + BridgedStmts_singleton (bridgedStmt_assign_of_bridged_val name value hValue) + +theorem BridgedStmts_cons_assign + (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts (.assign name value :: stmts) := + BridgedStmts_cons (bridgedStmt_assign_of_bridged_val name value hValue) hStmts + +theorem BridgedStmts_singleton_letMany + (names : List String) (value : Compiler.Yul.YulExpr) : + BridgedStmts [.letMany names value] := + BridgedStmts_singleton (bridgedStmt_letMany names value) + +theorem BridgedStmts_cons_letMany + (names : List String) (value : Compiler.Yul.YulExpr) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts (.letMany names value :: stmts) := + BridgedStmts_cons (bridgedStmt_letMany names value) hStmts + +theorem BridgedStmts_singleton_stop : + BridgedStmts + [Compiler.Yul.YulStmt.expr (Compiler.Yul.YulExpr.call "stop" [])] := + BridgedStmts_singleton bridgedStmt_stop + +theorem BridgedStmts_cons_stop {stmts : List Compiler.Yul.YulStmt} + (hStmts : BridgedStmts stmts) : + BridgedStmts + (Compiler.Yul.YulStmt.expr (Compiler.Yul.YulExpr.call "stop" []) :: stmts) := + BridgedStmts_cons bridgedStmt_stop hStmts + +theorem BridgedStmts_singleton_leave : + BridgedStmts [Compiler.Yul.YulStmt.leave] := + BridgedStmts_singleton bridgedStmt_leave + +theorem BridgedStmts_cons_leave {stmts : List Compiler.Yul.YulStmt} + (hStmts : BridgedStmts stmts) : + BridgedStmts (Compiler.Yul.YulStmt.leave :: stmts) := + BridgedStmts_cons bridgedStmt_leave hStmts + +theorem BridgedStmts_singleton_return + (offsetExpr sizeExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : + BridgedStmts [.expr (.call "return" [offsetExpr, sizeExpr])] := + BridgedStmts_singleton + (bridgedStmt_return_of_bridged_args offsetExpr sizeExpr hOffset hSize) + +theorem BridgedStmts_cons_return + (offsetExpr sizeExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts (.expr (.call "return" [offsetExpr, sizeExpr]) :: stmts) := + BridgedStmts_cons + (bridgedStmt_return_of_bridged_args offsetExpr sizeExpr hOffset hSize) hStmts + +theorem BridgedStmts_singleton_revert + (offsetExpr sizeExpr : Compiler.Yul.YulExpr) : + BridgedStmts [.expr (.call "revert" [offsetExpr, sizeExpr])] := + BridgedStmts_singleton (bridgedStmt_revert offsetExpr sizeExpr) + +theorem BridgedStmts_cons_revert + (offsetExpr sizeExpr : Compiler.Yul.YulExpr) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts (.expr (.call "revert" [offsetExpr, sizeExpr]) :: stmts) := + BridgedStmts_cons (bridgedStmt_revert offsetExpr sizeExpr) hStmts + +theorem BridgedStmts_singleton_mstore + (offsetExpr valExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : + BridgedStmts [.expr (.call "mstore" [offsetExpr, valExpr])] := + BridgedStmts_singleton + (bridgedStmt_mstore_of_bridged_args offsetExpr valExpr hOffset hVal) + +theorem BridgedStmts_cons_mstore + (offsetExpr valExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts (.expr (.call "mstore" [offsetExpr, valExpr]) :: stmts) := + BridgedStmts_cons + (bridgedStmt_mstore_of_bridged_args offsetExpr valExpr hOffset hVal) hStmts + +theorem BridgedStmts_singleton_tstore + (offsetExpr valExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : + BridgedStmts [.expr (.call "tstore" [offsetExpr, valExpr])] := + BridgedStmts_singleton + (bridgedStmt_tstore_of_bridged_args offsetExpr valExpr hOffset hVal) + +theorem BridgedStmts_cons_tstore + (offsetExpr valExpr : Compiler.Yul.YulExpr) + (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts (.expr (.call "tstore" [offsetExpr, valExpr]) :: stmts) := + BridgedStmts_cons + (bridgedStmt_tstore_of_bridged_args offsetExpr valExpr hOffset hVal) hStmts + +theorem BridgedStmts_singleton_sstore_lit + (slot : Nat) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) : + BridgedStmts [.expr (.call "sstore" [.lit slot, valExpr])] := + BridgedStmts_singleton + (bridgedStmt_sstore_lit_of_bridged_val slot valExpr hVal) + +theorem BridgedStmts_cons_sstore_lit + (slot : Nat) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts (.expr (.call "sstore" [.lit slot, valExpr]) :: stmts) := + BridgedStmts_cons + (bridgedStmt_sstore_lit_of_bridged_val slot valExpr hVal) hStmts + +theorem BridgedStmts_singleton_sstore_ident + (slotName : String) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) : + BridgedStmts [.expr (.call "sstore" [.ident slotName, valExpr])] := + BridgedStmts_singleton + (bridgedStmt_sstore_ident_of_bridged_val slotName valExpr hVal) + +theorem BridgedStmts_cons_sstore_ident + (slotName : String) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts (.expr (.call "sstore" [.ident slotName, valExpr]) :: stmts) := + BridgedStmts_cons + (bridgedStmt_sstore_ident_of_bridged_val slotName valExpr hVal) hStmts + +theorem BridgedStmts_singleton_sstore_mapping + (baseExpr keyExpr valExpr : Compiler.Yul.YulExpr) + (hBase : BridgedExpr baseExpr) (hKey : BridgedExpr keyExpr) + (hVal : BridgedExpr valExpr) : + BridgedStmts + [.expr (.call "sstore" [.call "mappingSlot" [baseExpr, keyExpr], valExpr])] := + BridgedStmts_singleton + (bridgedStmt_sstore_mapping_of_bridged_args + baseExpr keyExpr valExpr hBase hKey hVal) + +theorem BridgedStmts_cons_sstore_mapping + (baseExpr keyExpr valExpr : Compiler.Yul.YulExpr) + (hBase : BridgedExpr baseExpr) (hKey : BridgedExpr keyExpr) + (hVal : BridgedExpr valExpr) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts + (.expr (.call "sstore" [.call "mappingSlot" [baseExpr, keyExpr], valExpr]) + :: stmts) := + BridgedStmts_cons + (bridgedStmt_sstore_mapping_of_bridged_args + baseExpr keyExpr valExpr hBase hKey hVal) hStmts + +theorem BridgedStmts_singleton_log + (func : String) (args : List Compiler.Yul.YulExpr) + (hLog : isYulLogName func = true) + (hArgs : ∀ arg ∈ args, BridgedExpr arg) : + BridgedStmts [.expr (.call func args)] := + BridgedStmts_singleton + (bridgedStmt_log_of_bridged_args func args hLog hArgs) + +theorem BridgedStmts_cons_log + (func : String) (args : List Compiler.Yul.YulExpr) + (hLog : isYulLogName func = true) + (hArgs : ∀ arg ∈ args, BridgedExpr arg) + {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : + BridgedStmts (.expr (.call func args) :: stmts) := + BridgedStmts_cons + (bridgedStmt_log_of_bridged_args func args hLog hArgs) hStmts + +theorem BridgedStmts_singleton_funcDef + (name : String) (params rets : List String) + (body : List Compiler.Yul.YulStmt) : + BridgedStmts [.funcDef name params rets body] := + BridgedStmts_singleton (bridgedStmt_funcDef name params rets body) + +theorem BridgedStmts_cons_funcDef + (name : String) (params rets : List String) + (body stmts : List Compiler.Yul.YulStmt) (hStmts : BridgedStmts stmts) : + BridgedStmts (.funcDef name params rets body :: stmts) := + BridgedStmts_cons (bridgedStmt_funcDef name params rets body) hStmts + +end Compiler.Proofs.YulGeneration.Backends diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeTest.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeTest.lean index acc9bf8e5..52a058a2f 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeTest.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeTest.lean @@ -3,7 +3,7 @@ builtin bridge. Validates that `evalPureBuiltinViaEvmYulLean` (which delegates to - EVMYulLean's UInt256 operations) agrees with Verity's `evalBuiltinCall` + EVMYulLean's UInt256 operations) agrees with Verity's `legacyEvalBuiltinCall` on concrete test vectors for all pure arithmetic/comparison/bitwise builtins. This is a smoke test, not a general equivalence proof. Full semantic @@ -39,11 +39,11 @@ private def testBridgeCalldata : List Nat := [0xDEADBEEF] /-- Helper: evaluate a builtin via the Verity path. -/ private def verityEval (func : String) (args : List Nat) : Option Nat := - evalBuiltinCall testStorage testSender testSelector testCalldata func args + legacyEvalBuiltinCall testStorage testSender testSelector testCalldata func args /-- Helper: evaluate a builtin via the context-aware Verity path. -/ private def verityEvalWithContext (func : String) (args : List Nat) : Option Nat := - evalBuiltinCallWithContext + legacyEvalBuiltinCallWithContext testStorage testSender testMsgValue @@ -60,7 +60,7 @@ private def verityEvalWithContext (func : String) (args : List Nat) : Option Nat /-- Helper: evaluate a builtin via the context-aware Verity path with nontrivial selector/calldata for calldata bridge checks. -/ private def verityEvalWithBridgeCalldata (func : String) (args : List Nat) : Option Nat := - evalBuiltinCallWithContext + legacyEvalBuiltinCallWithContext testStorage testSender testMsgValue @@ -166,55 +166,55 @@ example : verityEval "iszero" [Compiler.Constants.evmModulus] = /-- Universal bridge theorem for `add` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "add" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "add" [a, b] = evalPureBuiltinViaEvmYulLean "add" [a, b] := by exact evalBuiltinCall_add_bridge storage sender selector calldata a b /-- Universal bridge theorem for `sub` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "sub" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "sub" [a, b] = evalPureBuiltinViaEvmYulLean "sub" [a, b] := by exact evalBuiltinCall_sub_bridge storage sender selector calldata a b /-- Universal bridge theorem for `mul` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "mul" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "mul" [a, b] = evalPureBuiltinViaEvmYulLean "mul" [a, b] := by exact evalBuiltinCall_mul_bridge storage sender selector calldata a b /-- Universal bridge theorem for `div` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "div" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "div" [a, b] = evalPureBuiltinViaEvmYulLean "div" [a, b] := by exact evalBuiltinCall_div_bridge storage sender selector calldata a b /-- Universal bridge theorem for `mod` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "mod" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "mod" [a, b] = evalPureBuiltinViaEvmYulLean "mod" [a, b] := by exact evalBuiltinCall_mod_bridge storage sender selector calldata a b /-- Universal bridge theorem for `eq` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "eq" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "eq" [a, b] = evalPureBuiltinViaEvmYulLean "eq" [a, b] := by exact evalBuiltinCall_eq_bridge storage sender selector calldata a b /-- Universal bridge theorem for `iszero` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a : Nat) : - evalBuiltinCall storage sender selector calldata "iszero" [a] = + legacyEvalBuiltinCall storage sender selector calldata "iszero" [a] = evalPureBuiltinViaEvmYulLean "iszero" [a] := by exact evalBuiltinCall_iszero_bridge storage sender selector calldata a /-- Universal bridge theorem for `lt` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "lt" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "lt" [a, b] = evalPureBuiltinViaEvmYulLean "lt" [a, b] := by exact evalBuiltinCall_lt_bridge storage sender selector calldata a b /-- Universal bridge theorem for `gt` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "gt" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "gt" [a, b] = evalPureBuiltinViaEvmYulLean "gt" [a, b] := by exact evalBuiltinCall_gt_bridge storage sender selector calldata a b @@ -251,19 +251,19 @@ example : verityEval "xor" [Compiler.Constants.evmModulus, 0] = /-- Universal bridge theorem for `and` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "and" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "and" [a, b] = evalPureBuiltinViaEvmYulLean "and" [a, b] := by exact evalBuiltinCall_and_bridge storage sender selector calldata a b /-- Universal bridge theorem for `or` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "or" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "or" [a, b] = evalPureBuiltinViaEvmYulLean "or" [a, b] := by exact evalBuiltinCall_or_bridge storage sender selector calldata a b /-- Universal bridge theorem for `xor` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a b : Nat) : - evalBuiltinCall storage sender selector calldata "xor" [a, b] = + legacyEvalBuiltinCall storage sender selector calldata "xor" [a, b] = evalPureBuiltinViaEvmYulLean "xor" [a, b] := by exact evalBuiltinCall_xor_bridge storage sender selector calldata a b @@ -276,7 +276,7 @@ example : verityEval "not" [Compiler.Constants.evmModulus] = /-- Universal bridge theorem for `not` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (a : Nat) : - evalBuiltinCall storage sender selector calldata "not" [a] = + legacyEvalBuiltinCall storage sender selector calldata "not" [a] = evalPureBuiltinViaEvmYulLean "not" [a] := by exact evalBuiltinCall_not_bridge storage sender selector calldata a @@ -293,7 +293,7 @@ example : verityEval "shl" [Compiler.Constants.evmModulus - 1, 3] = /-- Universal bridge theorem for `shl` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (shift value : Nat) : - evalBuiltinCall storage sender selector calldata "shl" [shift, value] = + legacyEvalBuiltinCall storage sender selector calldata "shl" [shift, value] = evalPureBuiltinViaEvmYulLean "shl" [shift, value] := by exact evalBuiltinCall_shl_bridge storage sender selector calldata shift value @@ -310,7 +310,7 @@ example : verityEval "shr" [Compiler.Constants.evmModulus - 1, 12345] = /-- Universal bridge theorem for `shr` (symbolic, not vector-based). -/ example (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) (shift value : Nat) : - evalBuiltinCall storage sender selector calldata "shr" [shift, value] = + legacyEvalBuiltinCall storage sender selector calldata "shr" [shift, value] = evalPureBuiltinViaEvmYulLean "shr" [shift, value] := by exact evalBuiltinCall_shr_bridge storage sender selector calldata shift value @@ -729,7 +729,7 @@ example : verityEval "byte" [0, 0] = bridgeEval "byte" [0, 0] := by native_decid -- ## Context-lifted backend bridge (Phase 4 rewriting surface) -- -- These tests validate that `evalBuiltinCallWithBackendContext .evmYulLean` --- agrees with `evalBuiltinCallWithContext` on concrete inputs, exercising +-- agrees with `legacyEvalBuiltinCallWithContext` on concrete inputs, exercising -- the 25 context-lifted bridge theorems that are the primary rewrite target -- for Phase 4 retargeting. @@ -855,7 +855,8 @@ example : backendEvalWithContext "sload" [42] = example : backendEvalWithContext "mappingSlot" [0, 1] = verityEvalWithContext "mappingSlot" [0, 1] := by simp [backendEvalWithContext, verityEvalWithContext, evalBuiltinCallWithBackendContext, - evalBuiltinCallWithContext, evalBuiltinCallViaEvmYulLean] + evalBuiltinCallWithEvmYulLeanContext, legacyEvalBuiltinCallWithContext, + evalBuiltinCallViaEvmYulLean] /-- Context-lifted bridge: caller now reads the bridged execution context. -/ example : backendEvalWithContext "caller" [] = verityEvalWithContext "caller" [] := by native_decide @@ -874,7 +875,7 @@ example : backendEvalWithContext "calldatasize" [] = verityEvalWithContext "call /-- `calldatasize` is a UInt256 word observation, so Verity also reduces the bridged byte length modulo `2^256` rather than returning an unbounded Nat. -/ example (selector : Nat) (calldata : List Nat) : - evalBuiltinCallWithContext + legacyEvalBuiltinCallWithContext testStorage testSender testMsgValue @@ -888,7 +889,7 @@ example (selector : Nat) (calldata : List Nat) : "calldatasize" [] = some ((4 + calldata.length * 32) % Compiler.Constants.evmModulus) := by - simp [evalBuiltinCallWithContext, Compiler.Constants.evmModulus] + simp [legacyEvalBuiltinCallWithContext, Compiler.Constants.evmModulus] /-- Context-lifted bridge: callvalue now reads the bridged execution context. -/ example : backendEvalWithContext "callvalue" [] = verityEvalWithContext "callvalue" [] := by native_decide diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBuiltinSemantics.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBuiltinSemantics.lean new file mode 100644 index 000000000..5d73ae8ac --- /dev/null +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBuiltinSemantics.lean @@ -0,0 +1,71 @@ +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanAdapter + +namespace Compiler.Proofs.YulGeneration.Backends + +open Compiler.Proofs.IRGeneration (IRStorageWord IRStorageSlot) + +/-- Native EVMYulLean-backed builtin evaluation with full execution context. + +This is the native-default builtin surface used by public IR/Yul proof entry +points. Environment-only opcodes are handled directly from the context; all +ordinary, storage, calldata, and helper builtins are routed through +`evalBuiltinCallViaEvmYulLean`. -/ +def evalBuiltinCallWithEvmYulLeanContext + (storage : IRStorageSlot → IRStorageWord) + (sender : Nat) + (msgValue : Nat) + (thisAddress : Nat) + (blockTimestamp : Nat) + (blockNumber : Nat) + (chainId : Nat) + (blobBaseFee : Nat) + (selector : Nat) + (calldata : List Nat) + (func : String) + (argVals : List Nat) : Option Nat := + let toWord (x : Nat) : Nat := x % Compiler.Constants.evmModulus + if func = "caller" then + match argVals with + | [] => some sender + | _ => none + else if func = "address" then + match argVals with + | [] => some (toWord thisAddress) + | _ => none + else if func = "callvalue" then + match argVals with + | [] => some (toWord msgValue) + | _ => none + else if func = "timestamp" then + match argVals with + | [] => some (toWord blockTimestamp) + | _ => none + else if func = "number" then + match argVals with + | [] => some (toWord blockNumber) + | _ => none + else if func = "chainid" then + match argVals with + | [] => some (toWord chainId) + | _ => none + else if func = "blobbasefee" then + match argVals with + | [] => some (toWord blobBaseFee) + | _ => none + else if func = "calldatasize" then + match argVals with + | [] => some (toWord (4 + calldata.length * 32)) + | _ => none + else + evalBuiltinCallViaEvmYulLean storage sender selector calldata func argVals + +def evalBuiltinCallWithEvmYulLean + (storage : IRStorageSlot → IRStorageWord) + (sender : Nat) + (selector : Nat) + (calldata : List Nat) + (func : String) + (argVals : List Nat) : Option Nat := + evalBuiltinCallWithEvmYulLeanContext storage sender 0 0 0 0 0 0 selector calldata func argVals + +end Compiler.Proofs.YulGeneration.Backends diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeDispatchOracleTest.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeDispatchOracleTest.lean index 69bfcd702..db3b10440 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeDispatchOracleTest.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeDispatchOracleTest.lean @@ -1,6 +1,6 @@ import Compiler.CompilationModel import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanNativeHarness -import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanRetarget +import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics namespace Compiler.Proofs.YulGeneration.Backends.NativeDispatchOracleTest @@ -322,13 +322,202 @@ private def memoryRevertDispatchSmokeContract : IRContract := ] usesMapping := false } +/- Regression-only comparison oracle for this executable smoke test. The +production retarget executor in `EvmYulLeanRetarget.lean` stays private so it +cannot become public proof authority. -/ +mutual + +private def referenceEvalYulExprsWithBackend + (backend : BuiltinBackend) (state : YulState) : + List Compiler.Yul.YulExpr → Option (List Nat) + | [] => some [] + | e :: es => do + let v ← referenceEvalYulExprWithBackend backend state e + let vs ← referenceEvalYulExprsWithBackend backend state es + pure (v :: vs) +termination_by es => exprsSize es +decreasing_by + all_goals + simp [exprsSize] + omega + +private def referenceEvalYulCallWithBackend + (backend : BuiltinBackend) (state : YulState) + (func : String) : List Compiler.Yul.YulExpr → Option Nat + | args => do + let argVals ← referenceEvalYulExprsWithBackend backend state args + if func = "tload" then + match argVals with + | [slot] => some (state.transientStorage (slot % Compiler.Constants.evmModulus)) + | _ => none + else if func = "mload" then + match argVals with + | [offset] => some (state.memory offset) + | _ => none + else if func = "keccak256" then + match argVals with + | [offset, size] => some (abstractKeccakMemorySlice state.memory offset size) + | _ => none + else + evalBuiltinCallWithBackendContext backend + state.storage state.sender state.msgValue state.thisAddress state.blockTimestamp + state.blockNumber state.chainId state.blobBaseFee state.selector state.calldata func argVals +termination_by args => exprsSize args + 1 +decreasing_by + omega + +private def referenceEvalYulExprWithBackend + (backend : BuiltinBackend) (state : YulState) : + Compiler.Yul.YulExpr → Option Nat + | .lit n => some n + | .hex n => some n + | .str _ => none + | .ident name => state.getVar name + | .call func args => referenceEvalYulCallWithBackend backend state func args +termination_by e => exprSize e +decreasing_by + simp [exprSize] + +end + +private def referenceExecYulFuelWithBackend (backend : BuiltinBackend) : + Nat → YulState → YulExecTarget → YulExecResult + | _, state, .stmts [] => .continue state + | _, state, .stmt (Compiler.Yul.YulStmt.funcDef _ _ _ _) => .continue state + | 0, state, _ => .revert state + | Nat.succ fuel, state, target => + match target with + | .stmt stmt => + match stmt with + | .comment _ => .continue state + | .let_ name value => + match referenceEvalYulExprWithBackend backend state value with + | some v => .continue (state.setVar name v) + | none => .revert state + | .letMany _ _ => .revert state + | .assign name value => + match referenceEvalYulExprWithBackend backend state value with + | some v => .continue (state.setVar name v) + | none => .revert state + | .leave => .continue state + | .expr e => + match e with + | .call "sstore" [slotExpr, valExpr] => + match slotExpr with + | .call "mappingSlot" [baseExpr, keyExpr] => + match referenceEvalYulExprWithBackend backend state baseExpr, + referenceEvalYulExprWithBackend backend state keyExpr, + referenceEvalYulExprWithBackend backend state valExpr with + | some baseSlot, some key, some val => + let updated := Compiler.Proofs.abstractStoreMappingEntry + state.storage baseSlot key val + .continue { state with storage := updated } + | _, _, _ => .revert state + | _ => + match referenceEvalYulExprWithBackend backend state slotExpr, + referenceEvalYulExprWithBackend backend state valExpr with + | some slot, some val => + let updated := Compiler.Proofs.abstractStoreStorageOrMapping + state.storage slot val + .continue { state with storage := updated } + | _, _ => .revert state + | .call "mstore" [offsetExpr, valExpr] => + match referenceEvalYulExprWithBackend backend state offsetExpr, + referenceEvalYulExprWithBackend backend state valExpr with + | some offset, some val => + .continue { state with + memory := fun o => if o = offset then val else state.memory o } + | _, _ => .revert state + | .call "tstore" [offsetExpr, valExpr] => + match referenceEvalYulExprWithBackend backend state offsetExpr, + referenceEvalYulExprWithBackend backend state valExpr with + | some offset, some val => + .continue { state with + transientStorage := fun o => + if o = offset then val else state.transientStorage o } + | _, _ => .revert state + | .call "stop" [] => .stop state + | .call "return" [offsetExpr, sizeExpr] => + match referenceEvalYulExprWithBackend backend state offsetExpr, + referenceEvalYulExprWithBackend backend state sizeExpr with + | some offset, some size => + if size = 32 then + .return (state.memory offset) state + else + .return 0 state + | _, _ => .revert state + | .call "revert" [_, _] => .revert state + | .call func args => + if isYulLogName func then + match referenceEvalYulExprsWithBackend backend state args with + | some argVals => + match applyYulLogCall? state func argVals with + | some next => .continue next + | none => .revert state + | none => .revert state + else + match referenceEvalYulExprWithBackend backend state e with + | some _ => .continue state + | none => .revert state + | _ => + match referenceEvalYulExprWithBackend backend state e with + | some _ => .continue state + | none => .revert state + | .if_ cond body => + match referenceEvalYulExprWithBackend backend state cond with + | some v => + if v = 0 then + .continue state + else + referenceExecYulFuelWithBackend backend fuel state (.stmts body) + | none => .revert state + | .switch expr cases defaultCase => + match referenceEvalYulExprWithBackend backend state expr with + | some v => + match cases.find? (fun x => decide (x.fst = v)) with + | some (_, body) => + referenceExecYulFuelWithBackend backend fuel state (.stmts body) + | none => + match defaultCase with + | some body => + referenceExecYulFuelWithBackend backend fuel state (.stmts body) + | none => .continue state + | none => .revert state + | .for_ init cond post body => + match referenceExecYulFuelWithBackend backend fuel state (.stmts init) with + | .continue s' => + match referenceEvalYulExprWithBackend backend s' cond with + | some v => + if v = 0 then .continue s' + else + match referenceExecYulFuelWithBackend backend fuel s' (.stmts body) with + | .continue s'' => + match referenceExecYulFuelWithBackend backend fuel s'' (.stmts post) with + | .continue s''' => + referenceExecYulFuelWithBackend backend fuel s''' + (.stmt (.for_ [] cond post body)) + | other => other + | other => other + | none => .revert s' + | other => other + | .block stmts => + referenceExecYulFuelWithBackend backend fuel state (.stmts stmts) + | .funcDef _ _ _ _ => .continue state + | .stmts [] => .continue state + | .stmts (stmt :: rest) => + match referenceExecYulFuelWithBackend backend fuel state (.stmt stmt) with + | .continue s' => referenceExecYulFuelWithBackend backend fuel s' (.stmts rest) + | .return v s => .return v s + | .stop s => .stop s + | .revert s => .revert s + private def referenceRuntimeWithBackendFuel (fuel : Nat) (runtimeCode : List Compiler.Yul.YulStmt) (tx : YulTransaction) (storage : IRStorageSlot -> IRStorageWord) (events : List (List Nat)) : YulResult := let initialState := YulState.initial tx storage events yulResultOfExecWithRollback initialState - (execYulFuelWithBackend .evmYulLean fuel initialState (.stmts runtimeCode)) + (referenceExecYulFuelWithBackend .evmYulLean fuel initialState (.stmts runtimeCode)) private def resultsMatchOnSlots (slots : List Nat) (nativeResult referenceResult : YulResult) : Bool := diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean index ab903afbf..b682b2482 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean @@ -1,6 +1,7 @@ import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanAdapter +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgePredicates import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanStateBridge -import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics +import Compiler.Proofs.YulGeneration.RuntimeTypes import Compiler.Codegen import EvmYul.Yul.Interpreter import Lean @@ -11,7 +12,8 @@ open Compiler.Yul open Compiler.Proofs.YulGeneration open Compiler.Proofs.YulGeneration.Backends.StateBridge open Lean Elab Tactic Meta -open Compiler.Proofs.IRGeneration (IRStorageWord IRStorageSlot) +open Compiler.Proofs.IRGeneration + (IRResult IRState IRStorageSlot IRStorageWord IRTransaction) /-! Executable native EVMYulLean runtime harness for #1737. @@ -99,6 +101,14 @@ def materializedStorageSlots -- partial literal-read collector for baseline storage projection facts. 0 :: yulStmtsLiteralStorageReadSlots runtimeCode ++ observableSlots +theorem observableSlot_mem_materializedStorageSlots + (runtimeCode : List YulStmt) + (observableSlots : List Nat) + (slot : Nat) + (hSlot : slot ∈ observableSlots) : + slot ∈ materializedStorageSlots runtimeCode observableSlots := by + simp [materializedStorageSlots, hSlot] + /-! ## Native Environment Support Boundary -/ partial def yulExprUsesBuiltinExceptFunctions @@ -178,10 +188,29 @@ def yulFunctionBodies (runtimeCode : List YulStmt) : List (String × List YulStm | .funcDef name _ _ body => some (name, body) | _ => none +@[simp] theorem yulFunctionBodies_nil : + yulFunctionBodies [] = [] := by + rfl + +@[simp] theorem yulFunctionBodies_funcDef_cons + (name : String) (params rets : List String) (body rest : List YulStmt) : + yulFunctionBodies (YulStmt.funcDef name params rets body :: rest) = + (name, body) :: yulFunctionBodies rest := by + rfl + +@[simp] theorem yulFunctionBodies_nonFunc_cons + (stmt : YulStmt) (rest : List YulStmt) + (hNoFunc : ∀ name params rets body, + stmt ≠ YulStmt.funcDef name params rets body) : + yulFunctionBodies (stmt :: rest) = yulFunctionBodies rest := by + cases stmt <;> simp [yulFunctionBodies] + case funcDef name params rets body => + exact False.elim (hNoFunc name params rets body rfl) + /-! ## Generated Native Runtime Fragment -/ mutual - partial def yulStmtContainsFuncDef : YulStmt → Bool + def yulStmtContainsFuncDef : YulStmt → Bool | .funcDef _ _ _ _ => true | .if_ _ body => yulStmtsContainFuncDef body | .for_ init _ post body => @@ -189,15 +218,243 @@ mutual yulStmtsContainFuncDef post || yulStmtsContainFuncDef body | .switch _ cases defaultBody => - cases.any (fun entry => yulStmtsContainFuncDef entry.2) || - defaultBody.any yulStmtsContainFuncDef + yulSwitchCasesContainFuncDef cases || + match defaultBody with + | some stmts => yulStmtsContainFuncDef stmts + | none => false | .block stmts => yulStmtsContainFuncDef stmts | .comment _ | .let_ _ _ | .letMany _ _ | .assign _ _ | .expr _ | .leave => false - partial def yulStmtsContainFuncDef (stmts : List YulStmt) : Bool := - stmts.any yulStmtContainsFuncDef + def yulStmtsContainFuncDef : List YulStmt → Bool + | [] => false + | stmt :: rest => yulStmtContainsFuncDef stmt || yulStmtsContainFuncDef rest + + def yulSwitchCasesContainFuncDef : List (Nat × List YulStmt) → Bool + | [] => false + | (_, body) :: rest => + yulStmtsContainFuncDef body || yulSwitchCasesContainFuncDef rest +end + +@[simp] theorem yulStmtsContainFuncDef_nil : + yulStmtsContainFuncDef [] = false := by + rfl + +@[simp] theorem yulStmtsContainFuncDef_cons + (stmt : YulStmt) (stmts : List YulStmt) : + yulStmtsContainFuncDef (stmt :: stmts) = + (yulStmtContainsFuncDef stmt || yulStmtsContainFuncDef stmts) := by + rfl + +@[simp] theorem yulStmtsContainFuncDef_append + (xs ys : List YulStmt) : + yulStmtsContainFuncDef (xs ++ ys) = + (yulStmtsContainFuncDef xs || yulStmtsContainFuncDef ys) := by + induction xs with + | nil => + simp + | cons stmt rest ih => + simp [ih, Bool.or_assoc] + +theorem yulStmtsContainFuncDef_flatMap_false {α : Type} + (xs : List α) (f : α → List YulStmt) + (h : ∀ x, x ∈ xs → yulStmtsContainFuncDef (f x) = false) : + yulStmtsContainFuncDef (xs.flatMap f) = false := by + induction xs with + | nil => + simp + | cons x rest ih => + have hx := h x (by simp) + have hrest : ∀ y, y ∈ rest → yulStmtsContainFuncDef (f y) = false := by + intro y hy + exact h y (by simp [hy]) + simp only [List.flatMap, List.map_cons, List.flatten_cons, + yulStmtsContainFuncDef_append, hx, Bool.false_or] + exact ih hrest + +mutual +/-- Native statement-group lowering succeeds for any statement with no nested +function definitions. The native lowerer only rejects inline `funcDef`s; this +lemma packages that structural totality fact for generated-runtime proofs. -/ +theorem lowerStmtGroupNativeWithSwitchIds_ok_of_yulStmtContainsFuncDef_false + (reservedNames : List String) (nextSwitchId : Nat) (stmt : YulStmt) + (hNoFunc : yulStmtContainsFuncDef stmt = false) : + ∃ (native : List EvmYul.Yul.Ast.Stmt) (next : Nat), + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId stmt = + .ok (native, next) := by + cases stmt with + | comment c => simp + | let_ name value => simp + | letMany names value => simp + | assign name value => simp + | expr e => simp + | «leave» => simp + | if_ cond body => + have hBody : yulStmtsContainFuncDef body = false := by + simpa [yulStmtContainsFuncDef] using hNoFunc + rcases + lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames nextSwitchId body hBody with + ⟨bodyNative, next, hLowerBody⟩ + refine ⟨[.If (Backends.lowerExprNative cond) bodyNative], next, ?_⟩ + simp [Backends.lowerStmtGroupNativeWithSwitchIds, hLowerBody] + | for_ init cond post body => + have hAll : + (yulStmtsContainFuncDef init = false ∧ + yulStmtsContainFuncDef post = false) ∧ + yulStmtsContainFuncDef body = false := by + simpa [yulStmtContainsFuncDef] using hNoFunc + rcases + lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames nextSwitchId init hAll.1.1 with + ⟨initNative, afterInit, hLowerInit⟩ + rcases + lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames afterInit post hAll.1.2 with + ⟨postNative, afterPost, hLowerPost⟩ + rcases + lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames afterPost body hAll.2 with + ⟨bodyNative, next, hLowerBody⟩ + refine + ⟨initNative ++ [.For (Backends.lowerExprNative cond) postNative bodyNative], + next, ?_⟩ + rw [Backends.lowerStmtGroupNativeWithSwitchIds] + rw [hLowerInit] + simp only [Bind.bind, Except.bind] + rw [hLowerPost] + simp + rw [hLowerBody] + simp [Pure.pure, Except.pure] + | «switch» expr cases defaultCase => + cases defaultCase with + | none => + have hCases : yulSwitchCasesContainFuncDef cases = false := by + simpa [yulStmtContainsFuncDef] using hNoFunc + rcases + lowerSwitchCasesNativeWithSwitchIds_ok_of_yulSwitchCasesContainFuncDef_false + reservedNames (Backends.freshNativeSwitchId reservedNames nextSwitchId + 1) + cases hCases with + ⟨casesNative, next, hLowerCases⟩ + refine + ⟨[Backends.lowerNativeSwitchBlock expr + (Backends.freshNativeSwitchId reservedNames nextSwitchId) + casesNative []], + next, ?_⟩ + simp [Backends.lowerStmtGroupNativeWithSwitchIds, hLowerCases] + | some defaultBody => + have hAll : + yulSwitchCasesContainFuncDef cases = false ∧ + yulStmtsContainFuncDef defaultBody = false := by + simpa [yulStmtContainsFuncDef] using hNoFunc + rcases + lowerSwitchCasesNativeWithSwitchIds_ok_of_yulSwitchCasesContainFuncDef_false + reservedNames (Backends.freshNativeSwitchId reservedNames nextSwitchId + 1) + cases hAll.1 with + ⟨casesNative, afterCases, hLowerCases⟩ + rcases + lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames afterCases defaultBody hAll.2 with + ⟨defaultNative, next, hLowerDefault⟩ + refine + ⟨[Backends.lowerNativeSwitchBlock expr + (Backends.freshNativeSwitchId reservedNames nextSwitchId) + casesNative defaultNative], + next, ?_⟩ + rw [Backends.lowerStmtGroupNativeWithSwitchIds] + simp only [hLowerCases, Bind.bind, Except.bind] + rw [hLowerDefault] + simp [Pure.pure, Except.pure] + | block stmts => + have hStmts : yulStmtsContainFuncDef stmts = false := by + simpa [yulStmtContainsFuncDef] using hNoFunc + rcases + lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames nextSwitchId stmts hStmts with + ⟨stmtsNative, next, hLowerStmts⟩ + refine ⟨[.Block stmtsNative], next, ?_⟩ + simp [Backends.lowerStmtGroupNativeWithSwitchIds, hLowerStmts] + | funcDef name params rets body => + simp [yulStmtContainsFuncDef] at hNoFunc + +/-- Native statement-list lowering succeeds for statement lists with no nested +function definitions. -/ +theorem lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + (reservedNames : List String) (nextSwitchId : Nat) (stmts : List YulStmt) + (hNoFunc : yulStmtsContainFuncDef stmts = false) : + ∃ (native : List EvmYul.Yul.Ast.Stmt) (next : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames nextSwitchId stmts = + .ok (native, next) := by + cases stmts with + | nil => + exact ⟨[], nextSwitchId, Backends.lowerStmtsNativeWithSwitchIds_nil _ _⟩ + | cons stmt rest => + have hAll : + yulStmtContainsFuncDef stmt = false ∧ + yulStmtsContainFuncDef rest = false := by + simpa [yulStmtsContainFuncDef] using hNoFunc + rcases + lowerStmtGroupNativeWithSwitchIds_ok_of_yulStmtContainsFuncDef_false + reservedNames nextSwitchId stmt hAll.1 with + ⟨headNative, midSwitchId, hLowerHead⟩ + rcases + lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames midSwitchId rest hAll.2 with + ⟨restNative, finalSwitchId, hLowerRest⟩ + refine ⟨headNative ++ restNative, finalSwitchId, ?_⟩ + rw [Backends.lowerStmtsNativeWithSwitchIds_cons] + rw [hLowerHead] + simp only [Bind.bind, Except.bind] + rw [hLowerRest] + simp [Pure.pure, Except.pure] + +/-- Native switch-case lowering succeeds when every case body has no nested +function definitions. -/ +theorem lowerSwitchCasesNativeWithSwitchIds_ok_of_yulSwitchCasesContainFuncDef_false + (reservedNames : List String) (nextSwitchId : Nat) + (cases : List (Nat × List YulStmt)) + (hNoFunc : yulSwitchCasesContainFuncDef cases = false) : + ∃ (native : List (Nat × List EvmYul.Yul.Ast.Stmt)) (next : Nat), + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames nextSwitchId cases = + .ok (native, next) := by + cases cases with + | nil => + exact ⟨[], nextSwitchId, + Backends.lowerSwitchCasesNativeWithSwitchIds_nil _ _⟩ + | cons entry rest => + rcases entry with ⟨tag, body⟩ + have hAll : + yulStmtsContainFuncDef body = false ∧ + yulSwitchCasesContainFuncDef rest = false := by + simpa [yulSwitchCasesContainFuncDef] using hNoFunc + rcases + lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + reservedNames nextSwitchId body hAll.1 with + ⟨bodyNative, midSwitchId, hLowerBody⟩ + rcases + lowerSwitchCasesNativeWithSwitchIds_ok_of_yulSwitchCasesContainFuncDef_false + reservedNames midSwitchId rest hAll.2 with + ⟨restNative, finalSwitchId, hLowerRest⟩ + refine ⟨(tag, bodyNative) :: restNative, finalSwitchId, ?_⟩ + rw [Backends.lowerSwitchCasesNativeWithSwitchIds_cons] + rw [hLowerBody] + simp only [Bind.bind, Except.bind] + rw [hLowerRest] + simp [Pure.pure, Except.pure] end +/-- Public wrapper for native statement-list lowering totality. -/ +theorem lowerStmtsNative_ok_of_yulStmtsContainFuncDef_false + (stmts : List YulStmt) + (hNoFunc : yulStmtsContainFuncDef stmts = false) : + ∃ native, Backends.lowerStmtsNative stmts = .ok native := by + rcases + lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + (Backends.yulStmtsIdentifierNames stmts) 0 stmts hNoFunc with + ⟨native, next, hLower⟩ + refine ⟨native, ?_⟩ + simp [Backends.lowerStmtsNative, hLower, Bind.bind, Except.bind, + Pure.pure, Except.pure] + def yulRuntimeTopLevelFunctionNames (runtimeCode : List YulStmt) : List String := runtimeCode.filterMap fun | .funcDef name _ _ _ => some name @@ -208,6 +465,73 @@ def yulRuntimeDispatcherStmts (runtimeCode : List YulStmt) : List YulStmt := | .funcDef _ _ _ _ => false | _ => true +@[simp] theorem yulRuntimeTopLevelFunctionNames_nil : + yulRuntimeTopLevelFunctionNames [] = [] := by + rfl + +@[simp] theorem yulRuntimeTopLevelFunctionNames_funcDef_cons + (name : String) (params rets : List String) (body rest : List YulStmt) : + yulRuntimeTopLevelFunctionNames + (YulStmt.funcDef name params rets body :: rest) = + name :: yulRuntimeTopLevelFunctionNames rest := by + rfl + +@[simp] theorem yulRuntimeTopLevelFunctionNames_nonFunc_cons + (stmt : YulStmt) (rest : List YulStmt) + (hNoFunc : ∀ name params rets body, + stmt ≠ YulStmt.funcDef name params rets body) : + yulRuntimeTopLevelFunctionNames (stmt :: rest) = + yulRuntimeTopLevelFunctionNames rest := by + cases stmt <;> simp [yulRuntimeTopLevelFunctionNames] + case funcDef name params rets body => + exact False.elim (hNoFunc name params rets body rfl) + +@[simp] theorem yulRuntimeTopLevelFunctionNames_append + (left right : List YulStmt) : + yulRuntimeTopLevelFunctionNames (left ++ right) = + yulRuntimeTopLevelFunctionNames left ++ + yulRuntimeTopLevelFunctionNames right := by + induction left with + | nil => rfl + | cons stmt rest ih => + cases stmt <;> simp [yulRuntimeTopLevelFunctionNames] + +theorem yulRuntimeTopLevelFunctionNames_eq_nil_of_all_nonFunc + (stmts : List YulStmt) + (hNoFunc : ∀ stmt, stmt ∈ stmts → + ∀ name params rets body, stmt ≠ YulStmt.funcDef name params rets body) : + yulRuntimeTopLevelFunctionNames stmts = [] := by + induction stmts with + | nil => rfl + | cons stmt rest ih => + rw [yulRuntimeTopLevelFunctionNames_nonFunc_cons] + · exact ih (by + intro stmt hmem + exact hNoFunc stmt (by simp [hmem])) + · intro name params rets body h + exact hNoFunc stmt (by simp) name params rets body h + +@[simp] theorem yulRuntimeDispatcherStmts_nil : + yulRuntimeDispatcherStmts [] = [] := by + rfl + +@[simp] theorem yulRuntimeDispatcherStmts_funcDef_cons + (name : String) (params rets : List String) (body rest : List YulStmt) : + yulRuntimeDispatcherStmts + (YulStmt.funcDef name params rets body :: rest) = + yulRuntimeDispatcherStmts rest := by + rfl + +@[simp] theorem yulRuntimeDispatcherStmts_nonFunc_cons + (stmt : YulStmt) (rest : List YulStmt) + (hNoFunc : ∀ name params rets body, + stmt ≠ YulStmt.funcDef name params rets body) : + yulRuntimeDispatcherStmts (stmt :: rest) = + stmt :: yulRuntimeDispatcherStmts rest := by + cases stmt <;> simp [yulRuntimeDispatcherStmts] + case funcDef name params rets body => + exact False.elim (hNoFunc name params rets body rfl) + def stringListHasDuplicate : List String → Bool | [] => false | name :: rest => rest.contains name || stringListHasDuplicate rest @@ -223,6 +547,1763 @@ def generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs Bool := (yulFunctionBodies runtimeCode).all fun entry => !yulStmtsContainFuncDef entry.2 +@[simp] theorem generatedRuntimeDispatcherHasNoFuncDefs_funcDef_cons + (name : String) (params rets : List String) (body rest : List YulStmt) : + generatedRuntimeDispatcherHasNoFuncDefs + (YulStmt.funcDef name params rets body :: rest) = + generatedRuntimeDispatcherHasNoFuncDefs rest := by + simp [generatedRuntimeDispatcherHasNoFuncDefs] + +@[simp] theorem generatedRuntimeDispatcherHasNoFuncDefs_nonFunc_cons + (stmt : YulStmt) (rest : List YulStmt) + (hNoFunc : ∀ name params rets body, + stmt ≠ YulStmt.funcDef name params rets body) : + generatedRuntimeDispatcherHasNoFuncDefs (stmt :: rest) = + (!yulStmtContainsFuncDef stmt && + generatedRuntimeDispatcherHasNoFuncDefs rest) := by + simp [generatedRuntimeDispatcherHasNoFuncDefs, + yulRuntimeDispatcherStmts_nonFunc_cons stmt rest hNoFunc] + +@[simp] theorem generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_funcDef_cons + (name : String) (params rets : List String) (body rest : List YulStmt) : + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs + (YulStmt.funcDef name params rets body :: rest) = + (!yulStmtsContainFuncDef body && + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs rest) := by + simp [generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs] + +@[simp] theorem generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_nonFunc_cons + (stmt : YulStmt) (rest : List YulStmt) + (hNoFunc : ∀ name params rets body, + stmt ≠ YulStmt.funcDef name params rets body) : + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs (stmt :: rest) = + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs rest := by + simp [generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs, + yulFunctionBodies_nonFunc_cons stmt rest hNoFunc] + +theorem dispatchBody_noFuncDefs + (payable : Bool) (label : String) (body : List YulStmt) + (hBody : yulStmtsContainFuncDef body = false) : + yulStmtsContainFuncDef + (Compiler.CodegenCommon.dispatchBody payable label body) = false := by + cases payable <;> + simp [Compiler.CodegenCommon.dispatchBody, Compiler.CodegenCommon.callvalueGuard, + yulStmtContainsFuncDef, yulStmtsContainFuncDef, hBody] + +theorem buildSwitchCases_noFuncDefs + (funcs : List IRFunction) + (hBodies : ∀ fn, fn ∈ funcs → yulStmtsContainFuncDef fn.body = false) : + yulSwitchCasesContainFuncDef + (funcs.map fun fn => + (fn.selector, + Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" + (Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: fn.body))) = + false := by + induction funcs with + | nil => rfl + | cons fn rest ih => + have hFnBody : yulStmtsContainFuncDef fn.body = false := hBodies fn (by simp) + have hRest : ∀ fn, fn ∈ rest → yulStmtsContainFuncDef fn.body = false := by + intro fn hmem + exact hBodies fn (by simp [hmem]) + have hDispatch : + yulStmtsContainFuncDef + (Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" + (Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: fn.body)) = + false := by + apply dispatchBody_noFuncDefs + simp [Compiler.CodegenCommon.calldatasizeGuard, yulStmtContainsFuncDef, + yulStmtsContainFuncDef, hFnBody] + simp [yulSwitchCasesContainFuncDef, hDispatch, ih hRest] + +theorem buildSwitch_noFuncDefs_noFallback_noReceive + (funcs : List IRFunction) + (hBodies : ∀ fn, fn ∈ funcs → yulStmtsContainFuncDef fn.body = false) : + yulStmtContainsFuncDef + (Compiler.CodegenCommon.buildSwitch funcs none none) = false := by + have hCases := buildSwitchCases_noFuncDefs funcs hBodies + simpa [Compiler.CodegenCommon.buildSwitch, Compiler.CodegenCommon.defaultDispatchCase, + Compiler.CodegenCommon.dispatchBody, Compiler.CodegenCommon.calldatasizeGuard, + Compiler.CodegenCommon.callvalueGuard, yulStmtContainsFuncDef, + yulStmtsContainFuncDef, yulSwitchCasesContainFuncDef] using hCases + +/-- Dispatch body emitted for one external function case. This native-harness +copy avoids importing the legacy proof-interpreter `Codegen` module. -/ +def switchCaseBody (fn : IRFunction) : List YulStmt := + Compiler.CodegenCommon.dispatchBody fn.payable s!"{fn.name}()" + ([Compiler.CodegenCommon.calldatasizeGuard fn.params.length] ++ fn.body) + +/-- Switch cases generated from IR functions. -/ +def switchCases (fns : List IRFunction) : List (Nat × List YulStmt) := + fns.map (fun fn => (fn.selector, switchCaseBody fn)) + +/-- Source case list emitted inside `buildSwitch` before the optional default +case is attached. Kept explicit so native lowering lemmas can speak about the +actual generated dispatcher source list, not only the proof-side `switchCases` +abbreviation. -/ +def buildSwitchSourceCases (funcs : List IRFunction) : + List (Nat × List YulStmt) := + funcs.map (fun fn => + (fn.selector, switchCaseBody fn)) + +/-- The case list emitted by `buildSwitch` is the native-harness switch case +abbreviation. -/ +theorem buildSwitchSourceCases_eq_switchCases (funcs : List IRFunction) : + buildSwitchSourceCases funcs = switchCases funcs := by + rfl + +theorem find_switch_case_of_find_function + (fns : List IRFunction) (sel : Nat) (fn : IRFunction) + (hFind : fns.find? (fun f => f.selector == sel) = some fn) : + (switchCases fns).find? (fun (c, _) => c = sel) = + some (fn.selector, switchCaseBody fn) := by + induction fns with + | nil => + simp at hFind + | cons f rest ih => + by_cases hsel : f.selector = sel + · have hselb : (f.selector == sel) = true := by + simp [hsel] + have hFind' : some f = some fn := by + simpa [List.find?, hselb] using hFind + cases hFind' + simp [switchCases, hsel] + · have hselb : (f.selector == sel) = false := by + simp [hsel] + have hFind' : rest.find? (fun f => f.selector == sel) = some fn := by + simpa [List.find?, hselb] using hFind + have ih' := ih hFind' + simpa [switchCases, List.find?, hsel] using ih' + +theorem find_switch_case_of_find_function_eq_selector + (fns : List IRFunction) (sel : Nat) (fn : IRFunction) + (hFind : fns.find? (fun f => f.selector == sel) = some fn) : + (switchCases fns).find? (fun (c, _) => c = sel) = + some (sel, switchCaseBody fn) := by + have hCase := find_switch_case_of_find_function fns sel fn hFind + have hSel : fn.selector = sel := by + have h := List.find?_some hFind + simp at h + exact h + simpa [hSel] using hCase + +theorem find_switch_case_of_find_function_none + (fns : List IRFunction) (sel : Nat) + (hFind : fns.find? (fun f => f.selector == sel) = none) : + (switchCases fns).find? (fun (c, _) => c = sel) = none := by + induction fns with + | nil => + simp at hFind + simp [switchCases] + | cons f rest ih => + by_cases hsel : f.selector = sel + · have hselb : (f.selector == sel) = true := by + simp [hsel] + have hFind' : (some f : Option IRFunction) = none := by + simp [List.find?, hselb] at hFind + cases hFind' + · have hselb : (f.selector == sel) = false := by + simp [hsel] + have hFind' : rest.find? (fun f => f.selector == sel) = none := by + simpa [List.find?, hselb] using hFind + have ih' := ih hFind' + simpa [switchCases, List.find?, hsel] using ih' + +/-- Generated-dispatcher selector hit specialized to `IRFunction` lookup. + +This composes the source `buildSwitch` case lookup theorem with native switch +case lowering, yielding the lowered native body selected by the same function +selector that `interpretIR` found. -/ +theorem lowerSwitchCasesNativeWithSwitchIds_find?_some_of_find_function + (reservedNames : List String) (nextSwitchId final selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (hLower : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames nextSwitchId + (switchCases funcs) = .ok (cases', final)) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) : + ∃ body' bodyStart bodyEnd, + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) := by + have hCase : + (switchCases funcs).find? (fun entry => entry.1 == selector) = + some (selector, switchCaseBody fn) := by + simpa using + (find_switch_case_of_find_function_eq_selector funcs selector fn hFind) + exact Backends.lowerSwitchCasesNativeWithSwitchIds_find?_some + reservedNames nextSwitchId final selector selector (switchCaseBody fn) + (switchCases funcs) cases' hLower hCase + +/-- Generated-dispatcher selector miss specialized to `IRFunction` lookup. + +If `interpretIR` finds no function for the selector, native lowering preserves +that miss on the generated `buildSwitch` case list. -/ +theorem lowerSwitchCasesNativeWithSwitchIds_find?_none_of_find_function + (reservedNames : List String) (nextSwitchId final selector : Nat) + (funcs : List IRFunction) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (hLower : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames nextSwitchId + (switchCases funcs) = .ok (cases', final)) + (hFind : funcs.find? (fun f => f.selector == selector) = none) : + cases'.find? (fun entry => entry.1 == selector) = none := by + have hCase : + (switchCases funcs).find? (fun entry => entry.1 == selector) = none := by + simpa using + (find_switch_case_of_find_function_none funcs selector hFind) + exact Backends.lowerSwitchCasesNativeWithSwitchIds_find?_none + reservedNames nextSwitchId final selector (switchCases funcs) cases' + hLower hCase + +/-- `buildSwitch`-source variant of +`lowerSwitchCasesNativeWithSwitchIds_find?_some_of_find_function`. -/ +theorem lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_some_of_find_function + (reservedNames : List String) (nextSwitchId final selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (hLower : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames nextSwitchId + (buildSwitchSourceCases funcs) = .ok (cases', final)) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) : + ∃ body' bodyStart bodyEnd, + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) := by + rw [buildSwitchSourceCases_eq_switchCases] at hLower + exact lowerSwitchCasesNativeWithSwitchIds_find?_some_of_find_function + reservedNames nextSwitchId final selector funcs fn cases' hLower hFind + +/-- `buildSwitch`-source variant of +`lowerSwitchCasesNativeWithSwitchIds_find?_none_of_find_function`. -/ +theorem lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function + (reservedNames : List String) (nextSwitchId final selector : Nat) + (funcs : List IRFunction) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (hLower : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames nextSwitchId + (buildSwitchSourceCases funcs) = .ok (cases', final)) + (hFind : funcs.find? (fun f => f.selector == selector) = none) : + cases'.find? (fun entry => entry.1 == selector) = none := by + rw [buildSwitchSourceCases_eq_switchCases] at hLower + exact lowerSwitchCasesNativeWithSwitchIds_find?_none_of_find_function + reservedNames nextSwitchId final selector funcs cases' hLower hFind + +/-- A singleton non-`funcDef` runtime lowers exactly through statement lowering, +with an empty native function table. + +This is the generic native-lowering boundary used when generated runtime code +has only the dispatcher shell. -/ +theorem lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative + (stmt : YulStmt) + (hNoFunc : ∀ name params rets body, + stmt ≠ YulStmt.funcDef name params rets body) : + Backends.lowerRuntimeContractNative [stmt] = + match Backends.lowerStmtsNative [stmt] with + | .ok dispatcher => + .ok { dispatcher := .Block dispatcher + functions := (∅ : Backends.NativeFunctionMap) } + | .error err => .error err := by + unfold Backends.lowerRuntimeContractNative + unfold Backends.lowerStmtsNative + dsimp + rw [Backends.lowerRuntimeContractNativeAux_stmt_cons] + · rw [Backends.lowerStmtsNativeWithSwitchIds_cons] + cases hLower : + Backends.lowerStmtGroupNativeWithSwitchIds + (Backends.yulStmtsIdentifierNames [stmt]) 0 stmt with + | ok pair => + cases pair with + | mk lowered next => + simp [Bind.bind, Except.bind, Pure.pure, Except.pure, + Backends.lowerRuntimeContractNativeAux] + | error err => + simp [Bind.bind, Except.bind] + · exact hNoFunc + +/-- Singleton non-`funcDef` runtime lowering, preserving the caller's +reserved-name context and native function table. This is the form needed after +runtime helper definitions have already populated the native function map. -/ +theorem lowerRuntimeContractNativeAux_single_stmt_eq_lowerStmtsNativeWithSwitchIds + (reservedNames : List String) + (stmt : YulStmt) + (functions : Backends.NativeFunctionMap) + (hNoFunc : ∀ name params rets body, + stmt ≠ YulStmt.funcDef name params rets body) : + (Backends.lowerRuntimeContractNativeAux reservedNames [stmt] [] functions 0 >>= + fun a => + pure ({ dispatcher := EvmYul.Yul.Ast.Stmt.Block a.1 + functions := a.2.1 } : EvmYul.Yul.Ast.YulContract)) = + match Backends.lowerStmtsNativeWithSwitchIds reservedNames 0 [stmt] with + | .ok (dispatcher, _) => + .ok ({ dispatcher := EvmYul.Yul.Ast.Stmt.Block dispatcher + functions := functions } : EvmYul.Yul.Ast.YulContract) + | .error err => .error err := by + rw [Backends.lowerRuntimeContractNativeAux_stmt_cons] + · rw [Backends.lowerStmtsNativeWithSwitchIds_cons] + cases hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames 0 stmt with + | ok pair => + cases pair with + | mk lowered next => + simp [Bind.bind, Except.bind, Pure.pure, Except.pure, + Backends.lowerRuntimeContractNativeAux] + | error err => + simp [Bind.bind, Except.bind] + · exact hNoFunc + +/-- Helper-free, no-fallback/no-receive emitted runtimes are exactly the +single generated dispatcher shell. -/ +theorem emitYul_runtimeCode_eq_single_dispatcher_of_noMapping_noInternals_noFallback_noReceive + (contract : IRContract) + (hNoMapping : contract.usesMapping = false) + (hInternals : contract.internalFunctions = []) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) : + (Compiler.emitYul contract).runtimeCode = + [Compiler.CodegenCommon.buildSwitch contract.functions none none] := by + simp [Compiler.emitYul, Compiler.CodegenCommon.emitYul, + Compiler.CodegenCommon.runtimeCode, hNoMapping, hInternals, hNoFallback, + hNoReceive] + +/-- In the helper-free, no-fallback/no-receive generated case, native runtime +lowering reduces to lowering the single dispatcher shell. -/ +theorem lowerRuntimeContractNative_emitYul_noMapping_noInternals_noFallback_noReceive + (contract : IRContract) + (hNoMapping : contract.usesMapping = false) + (hInternals : contract.internalFunctions = []) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) : + Backends.lowerRuntimeContractNative (Compiler.emitYul contract).runtimeCode = + match Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch contract.functions none none] with + | .ok dispatcher => + .ok { dispatcher := .Block dispatcher + functions := (∅ : Backends.NativeFunctionMap) } + | .error err => .error err := by + rw [emitYul_runtimeCode_eq_single_dispatcher_of_noMapping_noInternals_noFallback_noReceive + contract hNoMapping hInternals hNoFallback hNoReceive] + exact lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative + (Compiler.CodegenCommon.buildSwitch contract.functions none none) + (by + intro name params rets body h + simp [Compiler.CodegenCommon.buildSwitch] at h) + +/-- If helper-free emitted runtime lowering succeeds, the successful contract is +exactly the native dispatcher shell produced by lowering the generated +dispatcher statement. -/ +theorem lowerRuntimeContractNative_emitYul_noMapping_ok_dispatcher + (contract : IRContract) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (hNoMapping : contract.usesMapping = false) + (hInternals : contract.internalFunctions = []) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) + (hLower : + Backends.lowerRuntimeContractNative (Compiler.emitYul contract).runtimeCode = + .ok nativeContract) : + ∃ dispatcher : List EvmYul.Yul.Ast.Stmt, + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch contract.functions none none] = + .ok dispatcher ∧ + nativeContract = + { dispatcher := .Block dispatcher + functions := (∅ : Backends.NativeFunctionMap) } := by + rw [lowerRuntimeContractNative_emitYul_noMapping_noInternals_noFallback_noReceive + contract hNoMapping hInternals hNoFallback hNoReceive] at hLower + cases hDispatcher : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch contract.functions none none] with + | ok dispatcher => + rw [hDispatcher] at hLower + simp only [Except.ok.injEq] at hLower + exact ⟨dispatcher, rfl, hLower.symm⟩ + | error err => + rw [hDispatcher] at hLower + simp at hLower + +/-- A `.block` head in native lowering surfaces as a singleton `.Block` output +when the lowering succeeds. -/ +theorem lowerStmtsNative_single_block_ok_singleton + (stmts : List YulStmt) + (lowered : List EvmYul.Yul.Ast.Stmt) + (h : Backends.lowerStmtsNative [YulStmt.block stmts] = .ok lowered) : + ∃ inner, lowered = [.Block inner] := by + unfold Backends.lowerStmtsNative at h + dsimp at h + rw [Backends.lowerStmtsNativeWithSwitchIds_cons] at h + rw [Backends.lowerStmtGroupNativeWithSwitchIds_block] at h + cases hInner : + Backends.lowerStmtsNativeWithSwitchIds + (Backends.yulStmtsIdentifierNames [YulStmt.block stmts]) + 0 stmts with + | error err => + rw [hInner] at h + simp only [Bind.bind, Except.bind, reduceCtorEq] at h + | ok pair => + cases pair with + | mk inner next => + rw [hInner] at h + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, + Backends.lowerStmtsNativeWithSwitchIds_nil, List.append_nil, + Except.ok.injEq] at h + exact ⟨inner, h.symm⟩ + +/-- A successful lowering of singleton `[.block stmts]` reveals exactly the +lowering result for the inner statement list. -/ +theorem lowerStmtsNative_block_stmts_eq + (stmts : List YulStmt) + (inner : List EvmYul.Yul.Ast.Stmt) + (h : Backends.lowerStmtsNative [YulStmt.block stmts] = .ok [.Block inner]) : + ∃ next : Nat, + Backends.lowerStmtsNativeWithSwitchIds + (Backends.yulStmtsIdentifierNames [YulStmt.block stmts]) + 0 stmts = .ok (inner, next) := by + unfold Backends.lowerStmtsNative at h + dsimp at h + rw [Backends.lowerStmtsNativeWithSwitchIds_cons] at h + rw [Backends.lowerStmtGroupNativeWithSwitchIds_block] at h + cases hInner : + Backends.lowerStmtsNativeWithSwitchIds + (Backends.yulStmtsIdentifierNames [YulStmt.block stmts]) + 0 stmts with + | error err => + rw [hInner] at h + simp only [Bind.bind, Except.bind, reduceCtorEq] at h + | ok pair => + cases pair with + | mk inner' next => + rw [hInner] at h + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, + Backends.lowerStmtsNativeWithSwitchIds_nil, List.append_nil, + Except.ok.injEq] at h + injection h with hStmt _ + injection hStmt with hEq + subst hEq + exact ⟨next, rfl⟩ + +/-- A successful reserved-context lowering of singleton `[.block stmts]` reveals +exactly the lowering result for the inner statement list. -/ +theorem lowerStmtsNativeWithSwitchIds_block_stmts_eq + (reservedNames : List String) (n0 : Nat) + (stmts : List YulStmt) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [YulStmt.block stmts] = .ok ([.Block inner], next)) : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 stmts = + .ok (inner, next) := by + rw [Backends.lowerStmtsNativeWithSwitchIds_cons] at h + rw [Backends.lowerStmtGroupNativeWithSwitchIds_block] at h + cases hInner : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 stmts with + | error err => + rw [hInner] at h + simp only [Bind.bind, Except.bind, reduceCtorEq] at h + | ok pair => + cases pair with + | mk inner' next' => + rw [hInner] at h + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, + Backends.lowerStmtsNativeWithSwitchIds_nil, List.append_nil, + Except.ok.injEq, Prod.mk.injEq] at h + obtain ⟨hList, hNext⟩ := h + injection hList with hBlock + injection hBlock with hInnerEq + subst hInnerEq + subst hNext + rfl + +/-- A `.let_`-headed statement-list lowering peels its head into a singleton +`.Let` statement and threads the unchanged switch counter through the tail. -/ +theorem lowerStmtsNativeWithSwitchIds_let_head_eq + (reservedNames : List String) (n0 : Nat) + (name : String) (value : YulExpr) + (rest : List YulStmt) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (YulStmt.let_ name value :: rest) = .ok (inner, next)) : + ∃ rest' : List EvmYul.Yul.Ast.Stmt, + inner = EvmYul.Yul.Ast.Stmt.Let [name] + (some (Backends.lowerExprNative value)) :: rest' ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 rest = + .ok (rest', next) := by + rw [Backends.lowerStmtsNativeWithSwitchIds_cons, + Backends.lowerStmtGroupNativeWithSwitchIds_let] at h + simp only [Bind.bind, Except.bind] at h + cases hRest : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 rest with + | error err => + rw [hRest] at h + simp only [reduceCtorEq] at h + | ok pair => + cases pair with + | mk rest' n => + rw [hRest] at h + simp only [Pure.pure, Except.pure, List.singleton_append, + Except.ok.injEq, Prod.mk.injEq] at h + obtain ⟨hList, hNat⟩ := h + subst hNat + exact ⟨rest', hList.symm, rfl⟩ + +/-- A `.comment`-headed statement-list lowering emits a native no-op +`.Block []` and threads the switch counter through the tail unchanged. +Generated dispatch cases start with such a label comment, so this is the first +peel needed before reasoning about their executable guards. -/ +theorem lowerStmtsNativeWithSwitchIds_comment_head_eq + (reservedNames : List String) (n0 : Nat) + (text : String) + (rest : List YulStmt) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (YulStmt.comment text :: rest) = .ok (inner, next)) : + ∃ rest' : List EvmYul.Yul.Ast.Stmt, + inner = EvmYul.Yul.Ast.Stmt.Block [] :: rest' ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 rest = + .ok (rest', next) := by + rw [Backends.lowerStmtsNativeWithSwitchIds_cons, + Backends.lowerStmtGroupNativeWithSwitchIds_comment] at h + simp only [Bind.bind, Except.bind] at h + cases hRest : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 rest with + | error err => + rw [hRest] at h + simp only [reduceCtorEq] at h + | ok pair => + cases pair with + | mk rest' n => + rw [hRest] at h + simp only [Pure.pure, Except.pure, List.singleton_append, + Except.ok.injEq, Prod.mk.injEq] at h + obtain ⟨hList, hNat⟩ := h + subst hNat + exact ⟨rest', hList.symm, rfl⟩ + +/-- An `.if_`-headed statement-list lowering peels its head into a singleton +`.If` statement and threads the body's switch-counter advance through the tail. -/ +theorem lowerStmtsNativeWithSwitchIds_if_head_eq + (reservedNames : List String) (n0 : Nat) + (cond : YulExpr) (body : List YulStmt) + (rest : List YulStmt) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (YulStmt.if_ cond body :: rest) = .ok (inner, next)) : + ∃ (body' : List EvmYul.Yul.Ast.Stmt) (midN : Nat) + (rest' : List EvmYul.Yul.Ast.Stmt), + inner = EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative cond) body' :: rest' ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 body = + .ok (body', midN) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames midN rest = + .ok (rest', next) := by + rw [Backends.lowerStmtsNativeWithSwitchIds_cons, + Backends.lowerStmtGroupNativeWithSwitchIds_if] at h + cases hBody : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 body with + | error _ => rw [hBody] at h; simp only [Bind.bind, Except.bind, reduceCtorEq] at h + | ok bodyPair => + obtain ⟨body', midN⟩ := bodyPair + rw [hBody] at h + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure] at h + cases hRest : Backends.lowerStmtsNativeWithSwitchIds reservedNames midN rest with + | error _ => + rw [hRest] at h; simp only [reduceCtorEq] at h + | ok restPair => + obtain ⟨rest', _⟩ := restPair + rw [hRest] at h + simp only [List.singleton_append, Except.ok.injEq, Prod.mk.injEq] at h + obtain ⟨hList, hNat⟩ := h + subst hNat + exact ⟨body', midN, rest', hList.symm, rfl, hRest⟩ + +/-- Successful native lowering of a payable generated switch-case body exposes +the label no-op, the calldata-size guard, and the lowered user body tail. -/ +theorem lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (hPayable : fn.payable = true) + (h : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (inner, next)) : + ∃ (guardBody bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + inner = + EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + guardBody :: + bodyNative ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) := by + have hShape : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (YulStmt.comment s!"{fn.name}()" :: + Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: + fn.body) = .ok (inner, next) := by + simpa [switchCaseBody, Compiler.CodegenCommon.dispatchBody, + Compiler.CodegenCommon.callvalueGuard, hPayable] using h + rcases lowerStmtsNativeWithSwitchIds_comment_head_eq + reservedNames n0 s!"{fn.name}()" + (Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: fn.body) + inner next hShape with + ⟨afterComment, hInner, hAfterComment⟩ + rcases lowerStmtsNativeWithSwitchIds_if_head_eq + reservedNames n0 + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)]) + [YulStmt.expr (Yul.YulExpr.call "revert" [Yul.YulExpr.lit 0, + Yul.YulExpr.lit 0])] + fn.body afterComment next hAfterComment with + ⟨guardBody, bodyStart, bodyNative, hAfterCommentShape, _hGuard, + hBody⟩ + refine ⟨guardBody, bodyNative, bodyStart, ?_, hBody⟩ + rw [hInner, hAfterCommentShape] + +/-- Successful native lowering of a non-payable generated switch-case body +exposes the label no-op, the callvalue guard, the calldata-size guard, and the +lowered user body tail. -/ +theorem lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (hPayable : fn.payable = false) + (h : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (inner, next)) : + ∃ (callvalueGuardBody calldataGuardBody bodyNative : + List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + inner = + EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + callvalueGuardBody :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + calldataGuardBody :: + bodyNative ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) := by + have hShape : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (YulStmt.comment s!"{fn.name}()" :: + Compiler.CodegenCommon.callvalueGuard :: + Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: + fn.body) = .ok (inner, next) := by + simpa [switchCaseBody, Compiler.CodegenCommon.dispatchBody, + Compiler.CodegenCommon.callvalueGuard, hPayable] using h + rcases lowerStmtsNativeWithSwitchIds_comment_head_eq + reservedNames n0 s!"{fn.name}()" + (Compiler.CodegenCommon.callvalueGuard :: + Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: fn.body) + inner next hShape with + ⟨afterComment, hInner, hAfterComment⟩ + rcases lowerStmtsNativeWithSwitchIds_if_head_eq + reservedNames n0 + (Yul.YulExpr.call "callvalue" []) + [YulStmt.expr (Yul.YulExpr.call "revert" [Yul.YulExpr.lit 0, + Yul.YulExpr.lit 0])] + (Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: fn.body) + afterComment next hAfterComment with + ⟨callvalueGuardBody, calldataGuardStart, afterCallvalue, + hAfterCommentShape, _hCallvalueGuard, hAfterCallvalue⟩ + rcases lowerStmtsNativeWithSwitchIds_if_head_eq + reservedNames calldataGuardStart + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)]) + [YulStmt.expr (Yul.YulExpr.call "revert" [Yul.YulExpr.lit 0, + Yul.YulExpr.lit 0])] + fn.body afterCallvalue next hAfterCallvalue with + ⟨calldataGuardBody, bodyStart, bodyNative, hAfterCallvalueShape, + _hCalldataGuard, hBody⟩ + refine ⟨callvalueGuardBody, calldataGuardBody, bodyNative, bodyStart, + ?_, hBody⟩ + rw [hInner, hAfterCommentShape, hAfterCallvalueShape] + +set_option linter.unusedSimpArgs false in +/-- A singleton `.switch`-headed statement-list lowering reduces to a singleton +`.lowerNativeSwitchBlock` over the same source expression. -/ +theorem lowerStmtsNativeWithSwitchIds_singleton_switch_eq + (reservedNames : List String) (n0 : Nat) + (expr : YulExpr) (cases : List (Nat × List YulStmt)) + (defaultCase : Option (List YulStmt)) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [YulStmt.switch expr cases defaultCase] = .ok (inner, next)) : + ∃ (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (default' : List EvmYul.Yul.Ast.Stmt), + inner = [Backends.lowerNativeSwitchBlock expr + (Backends.freshNativeSwitchId reservedNames n0) cases' default'] := by + rw [Backends.lowerStmtsNativeWithSwitchIds_cons, + Backends.lowerStmtGroupNativeWithSwitchIds_switch] at h + dsimp only [] at h + cases hCases : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) cases with + | error _ => + rw [hCases] at h; simp only [Bind.bind, Except.bind, reduceCtorEq] at h + | ok casesPair => + obtain ⟨cases', midN⟩ := casesPair + rw [hCases] at h + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure] at h + cases defaultCase with + | none => + simp only [Backends.lowerStmtsNativeWithSwitchIds_nil, + List.singleton_append, Except.ok.injEq, Prod.mk.injEq] at h + exact ⟨cases', [], h.1.symm⟩ + | some defaultBody => + dsimp only [] at h + cases hDef : Backends.lowerStmtsNativeWithSwitchIds + reservedNames midN defaultBody with + | error _ => + rw [hDef] at h + simp only [Bind.bind, Except.bind, reduceCtorEq] at h + | ok defaultPair => + obtain ⟨default', _⟩ := defaultPair + rw [hDef] at h + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, + Backends.lowerStmtsNativeWithSwitchIds_nil, + List.singleton_append, Except.ok.injEq, Prod.mk.injEq] at h + exact ⟨cases', default', h.1.symm⟩ + +def nativeRevertZeroZeroStmt : EvmYul.Yul.Ast.Stmt := + .ExprStmtCall + (.Call (Sum.inl (EvmYul.Operation.REVERT : EvmYul.Operation .Yul)) + [.Lit (EvmYul.UInt256.ofNat 0), .Lit (EvmYul.UInt256.ofNat 0)]) + +@[simp] theorem nativeStmtWriteNames_nativeRevertZeroZeroStmt : + Backends.nativeStmtWriteNames nativeRevertZeroZeroStmt = [] := by + simp [nativeRevertZeroZeroStmt, Backends.nativeStmtWriteNames] + +@[simp] theorem nativeStmtsWriteNames_singleton_nativeRevertZeroZeroStmt : + Backends.nativeStmtsWriteNames [nativeRevertZeroZeroStmt] = [] := by + simp [Backends.nativeStmtsWriteNames] + +theorem nativeSwitchTempsFreshForWrites_nil + (switchId : Nat) : + Backends.nativeSwitchTempsFreshForWrites switchId [] := by + simp [Backends.nativeSwitchTempsFreshForWrites] + +theorem nativeSwitchTempsFreshForWrites_nativeRevertZeroZeroStmt + (switchId : Nat) : + Backends.nativeSwitchTempsFreshForWrites switchId + (Backends.nativeStmtsWriteNames [nativeRevertZeroZeroStmt]) := by + simp [nativeSwitchTempsFreshForWrites_nil] + +theorem nativeStmtsWriteNames_payable_dispatch_guard_prefix + (fn : IRFunction) (bodyNative : List EvmYul.Yul.Ast.Stmt) : + Backends.nativeStmtsWriteNames + (EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + [nativeRevertZeroZeroStmt] :: + bodyNative) = + Backends.nativeStmtsWriteNames bodyNative := by + simp [Backends.nativeStmtsWriteNames, Backends.nativeStmtWriteNames] + +theorem nativeStmtsWriteNames_nonpayable_dispatch_guard_prefix + (fn : IRFunction) (bodyNative : List EvmYul.Yul.Ast.Stmt) : + Backends.nativeStmtsWriteNames + (EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + [nativeRevertZeroZeroStmt] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + [nativeRevertZeroZeroStmt] :: + bodyNative) = + Backends.nativeStmtsWriteNames bodyNative := by + simp [Backends.nativeStmtsWriteNames, Backends.nativeStmtWriteNames] + +/-- The singleton default-revert body lowers to the native `revert(0,0)` stmt +without advancing the native switch counter. -/ +theorem lowerStmtsNativeWithSwitchIds_revert_zero_zero + (reservedNames : List String) (n : Nat) : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n + [YulStmt.expr (YulExpr.call "revert" [YulExpr.lit 0, YulExpr.lit 0])] = + .ok ([nativeRevertZeroZeroStmt], n) := by + simp [Backends.lowerStmtsNativeWithSwitchIds, nativeRevertZeroZeroStmt, + Backends.lowerExprNative, Backends.lookupRuntimePrimOp] + rfl + +/-- Concrete generated-guard variant of +`lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq`: the payable case +prefix lowers the generated calldata-size guard body to +`[nativeRevertZeroZeroStmt]`. -/ +theorem lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_revert_eq + (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (hPayable : fn.payable = true) + (h : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (inner, next)) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + inner = + EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + [nativeRevertZeroZeroStmt] :: + bodyNative ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) := by + have hShape : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (YulStmt.comment s!"{fn.name}()" :: + Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: + fn.body) = .ok (inner, next) := by + simpa [switchCaseBody, Compiler.CodegenCommon.dispatchBody, + Compiler.CodegenCommon.callvalueGuard, hPayable] using h + rcases lowerStmtsNativeWithSwitchIds_comment_head_eq + reservedNames n0 s!"{fn.name}()" + (Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: fn.body) + inner next hShape with + ⟨afterComment, hInner, hAfterComment⟩ + rcases lowerStmtsNativeWithSwitchIds_if_head_eq + reservedNames n0 + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)]) + [YulStmt.expr (Yul.YulExpr.call "revert" [Yul.YulExpr.lit 0, + Yul.YulExpr.lit 0])] + fn.body afterComment next hAfterComment with + ⟨guardBody, bodyStart, bodyNative, hAfterCommentShape, hGuard, + hBody⟩ + have hGuardPair : + ([nativeRevertZeroZeroStmt], n0) = (guardBody, bodyStart) := by + exact Except.ok.inj + ((lowerStmtsNativeWithSwitchIds_revert_zero_zero reservedNames n0).symm.trans + hGuard) + have hGuardBody : guardBody = [nativeRevertZeroZeroStmt] := by + exact (congrArg Prod.fst hGuardPair).symm + refine ⟨bodyNative, bodyStart, ?_, hBody⟩ + rw [hInner, hAfterCommentShape, hGuardBody] + +theorem nativeStmtsWriteNames_lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq_body + (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (hPayable : fn.payable = true) + (h : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (inner, next)) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.nativeStmtsWriteNames inner = + Backends.nativeStmtsWriteNames bodyNative ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) := by + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_revert_eq + reservedNames n0 fn inner next hPayable h with + ⟨bodyNative, bodyStart, hInner, hBody⟩ + refine ⟨bodyNative, bodyStart, ?_, hBody⟩ + rw [hInner, nativeStmtsWriteNames_payable_dispatch_guard_prefix] + +/-- Concrete generated-guard variant of +`lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq`: the non-payable +case prefix lowers both generated revert bodies to `[nativeRevertZeroZeroStmt]`. +-/ +theorem lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq + (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (hPayable : fn.payable = false) + (h : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (inner, next)) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + inner = + EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + [nativeRevertZeroZeroStmt] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)])) + [nativeRevertZeroZeroStmt] :: + bodyNative ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) := by + have hShape : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (YulStmt.comment s!"{fn.name}()" :: + Compiler.CodegenCommon.callvalueGuard :: + Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: + fn.body) = .ok (inner, next) := by + simpa [switchCaseBody, Compiler.CodegenCommon.dispatchBody, + Compiler.CodegenCommon.callvalueGuard, hPayable] using h + rcases lowerStmtsNativeWithSwitchIds_comment_head_eq + reservedNames n0 s!"{fn.name}()" + (Compiler.CodegenCommon.callvalueGuard :: + Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: fn.body) + inner next hShape with + ⟨afterComment, hInner, hAfterComment⟩ + rcases lowerStmtsNativeWithSwitchIds_if_head_eq + reservedNames n0 + (Yul.YulExpr.call "callvalue" []) + [YulStmt.expr (Yul.YulExpr.call "revert" [Yul.YulExpr.lit 0, + Yul.YulExpr.lit 0])] + (Compiler.CodegenCommon.calldatasizeGuard fn.params.length :: fn.body) + afterComment next hAfterComment with + ⟨callvalueGuardBody, calldataGuardStart, afterCallvalue, + hAfterCommentShape, hCallvalueGuard, hAfterCallvalue⟩ + rcases lowerStmtsNativeWithSwitchIds_if_head_eq + reservedNames calldataGuardStart + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit (4 + fn.params.length * 32)]) + [YulStmt.expr (Yul.YulExpr.call "revert" [Yul.YulExpr.lit 0, + Yul.YulExpr.lit 0])] + fn.body afterCallvalue next hAfterCallvalue with + ⟨calldataGuardBody, bodyStart, bodyNative, hAfterCallvalueShape, + hCalldataGuard, hBody⟩ + have hCallvaluePair : + ([nativeRevertZeroZeroStmt], n0) = + (callvalueGuardBody, calldataGuardStart) := by + exact Except.ok.inj + ((lowerStmtsNativeWithSwitchIds_revert_zero_zero reservedNames n0).symm.trans + hCallvalueGuard) + have hCallvalueGuardBody : + callvalueGuardBody = [nativeRevertZeroZeroStmt] := by + exact (congrArg Prod.fst hCallvaluePair).symm + have hCalldataPair : + ([nativeRevertZeroZeroStmt], calldataGuardStart) = + (calldataGuardBody, bodyStart) := by + exact Except.ok.inj + ((lowerStmtsNativeWithSwitchIds_revert_zero_zero + reservedNames calldataGuardStart).symm.trans hCalldataGuard) + have hCalldataGuardBody : + calldataGuardBody = [nativeRevertZeroZeroStmt] := by + exact (congrArg Prod.fst hCalldataPair).symm + refine ⟨bodyNative, bodyStart, ?_, hBody⟩ + rw [hInner, hAfterCommentShape, hAfterCallvalueShape, + hCallvalueGuardBody, hCalldataGuardBody] + +theorem nativeStmtsWriteNames_lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq_body + (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (hPayable : fn.payable = false) + (h : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (inner, next)) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.nativeStmtsWriteNames inner = + Backends.nativeStmtsWriteNames bodyNative ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) := by + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq + reservedNames n0 fn inner next hPayable h with + ⟨bodyNative, bodyStart, hInner, hBody⟩ + refine ⟨bodyNative, bodyStart, ?_, hBody⟩ + rw [hInner, nativeStmtsWriteNames_nonpayable_dispatch_guard_prefix] + +private theorem nativeSwitchTempsFreshForNativeBodies_cons_of_lowerSwitchCasesNativeWithSwitchIds + (reservedNames : List String) (nextSwitchId final switchId tag : Nat) + (body : List YulStmt) (rest : List (Nat × List YulStmt)) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (defaultBody : List EvmYul.Yul.Ast.Stmt) + (hLower : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + nextSwitchId ((tag, body) :: rest) = .ok (cases', final)) + (hHeadFresh : + ∀ bodyNative bodyEnd, + Backends.lowerStmtsNativeWithSwitchIds reservedNames nextSwitchId body = + .ok (bodyNative, bodyEnd) → + Backends.nativeSwitchTempsFreshForWrites switchId + (Backends.nativeStmtsWriteNames bodyNative)) + (hRestFresh : + ∀ bodyNative bodyEnd restNative restEnd, + Backends.lowerStmtsNativeWithSwitchIds reservedNames nextSwitchId body = + .ok (bodyNative, bodyEnd) → + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames bodyEnd rest = .ok (restNative, restEnd) → + Backends.nativeSwitchTempsFreshForNativeBodies switchId restNative defaultBody) : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases' defaultBody := by + rw [Backends.lowerSwitchCasesNativeWithSwitchIds_cons] at hLower + cases hBody : Backends.lowerStmtsNativeWithSwitchIds reservedNames + nextSwitchId body with + | error err => + rw [hBody] at hLower + simp only [Bind.bind, Except.bind, reduceCtorEq] at hLower + | ok bodyPair => + obtain ⟨bodyNative, bodyEnd⟩ := bodyPair + rw [hBody] at hLower + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure] at hLower + cases hRest : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames bodyEnd rest with + | error err => + rw [hRest] at hLower + simp only [reduceCtorEq] at hLower + | ok restPair => + obtain ⟨restNative, restEnd⟩ := restPair + rw [hRest] at hLower + simp only [Except.ok.injEq, Prod.mk.injEq] at hLower + rcases hLower with ⟨hCases', hFinal⟩ + subst cases' + subst final + constructor + · intro tag' body' hMem + rcases (by simpa using hMem : (tag', body') = (tag, bodyNative) ∨ + (tag', body') ∈ restNative) with hHead | hTail + · cases hHead + exact hHeadFresh bodyNative bodyEnd hBody + · exact (hRestFresh bodyNative bodyEnd restNative restEnd hBody hRest).1 tag' body' hTail + · exact + (hRestFresh bodyNative bodyEnd restNative restEnd hBody hRest).2 + +theorem nativeSwitchTempsFreshForNativeBodies_of_lowerSwitchCasesNativeWithSwitchIds + (reservedNames : List String) (nextSwitchId final switchId : Nat) + (cases : List (Nat × List YulStmt)) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (hLower : + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames nextSwitchId + cases = .ok (cases', final)) + (hCaseFresh : + ∀ tag body bodyNative bodyStart bodyEnd, + (tag, body) ∈ cases → + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart body = + .ok (bodyNative, bodyEnd) → + Backends.nativeSwitchTempsFreshForWrites switchId + (Backends.nativeStmtsWriteNames bodyNative)) + (hDefaultFresh : + Backends.nativeSwitchTempsFreshForWrites switchId + (Backends.nativeStmtsWriteNames defaultBody)) : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases' + defaultBody := by + induction cases generalizing nextSwitchId cases' final with + | nil => + rw [Backends.lowerSwitchCasesNativeWithSwitchIds_nil] at hLower + rcases (by simpa using hLower : cases' = [] ∧ nextSwitchId = final) with + ⟨hCases', _⟩ + subst cases' + simp [Backends.nativeSwitchTempsFreshForNativeBodies, hDefaultFresh] + | cons head rest ih => + obtain ⟨tag, body⟩ := head + exact + nativeSwitchTempsFreshForNativeBodies_cons_of_lowerSwitchCasesNativeWithSwitchIds + reservedNames nextSwitchId final switchId tag body rest cases' + defaultBody hLower + (by + intro bodyNative bodyEnd hBody + exact hCaseFresh tag body bodyNative nextSwitchId bodyEnd + (by simp) hBody) + (by + intro bodyNative bodyEnd restNative restEnd _hBody hRest + exact ih bodyEnd restEnd restNative hRest (by + intro tag' body' bodyNative' bodyStart bodyEnd' hMem hLowerBody + exact hCaseFresh tag' body' bodyNative' bodyStart bodyEnd' + (by simp [hMem]) hLowerBody)) + +theorem nativeSwitchTempsFreshForNativeBodies_buildSwitchSourceCases_of_lowerSwitchCasesNativeWithSwitchIds_of_case_body_fresh + (reservedNames : List String) (n0 midN : Nat) + (funcs : List IRFunction) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (hLower : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN)) + (hCaseFresh : + ∀ fn bodyNative bodyStart bodyEnd, + fn ∈ funcs → + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (bodyNative, bodyEnd) → + Backends.nativeSwitchTempsFreshForWrites + (Backends.freshNativeSwitchId reservedNames n0) + (Backends.nativeStmtsWriteNames bodyNative)) : + Backends.nativeSwitchTempsFreshForNativeBodies + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt] := by + exact + nativeSwitchTempsFreshForNativeBodies_of_lowerSwitchCasesNativeWithSwitchIds + reservedNames (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (Backends.freshNativeSwitchId reservedNames n0) + (buildSwitchSourceCases funcs) cases' [nativeRevertZeroZeroStmt] hLower + (by + intro tag body bodyNative bodyStart bodyEnd hMem hLowerBody + simp only [buildSwitchSourceCases, List.mem_map] at hMem + rcases hMem with ⟨fn, hFnMem, hEq⟩ + cases hEq + exact hCaseFresh fn bodyNative bodyStart bodyEnd hFnMem hLowerBody) + (nativeSwitchTempsFreshForWrites_nativeRevertZeroZeroStmt + (Backends.freshNativeSwitchId reservedNames n0)) + +set_option linter.unusedSimpArgs false in +/-- A singleton switch whose default is `revert(0,0)` lowers to a singleton +native switch block with concrete `[nativeRevertZeroZeroStmt]` default body. -/ +theorem lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq + (reservedNames : List String) (n0 : Nat) + (expr : YulExpr) (cases : List (Nat × List YulStmt)) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [YulStmt.switch expr cases + (some [YulStmt.expr (YulExpr.call "revert" + [YulExpr.lit 0, YulExpr.lit 0])])] = .ok (inner, next)) : + ∃ (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), + inner = [Backends.lowerNativeSwitchBlock expr + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] := by + rw [Backends.lowerStmtsNativeWithSwitchIds_cons, + Backends.lowerStmtGroupNativeWithSwitchIds_switch] at h + dsimp only [] at h + cases hCases : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) cases with + | error _ => + rw [hCases] at h; simp only [Bind.bind, Except.bind, reduceCtorEq] at h + | ok casesPair => + obtain ⟨cases', midN⟩ := casesPair + rw [hCases] at h + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure] at h + rw [lowerStmtsNativeWithSwitchIds_revert_zero_zero] at h + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, + Backends.lowerStmtsNativeWithSwitchIds_nil, + List.singleton_append, Except.ok.injEq, Prod.mk.injEq] at h + exact ⟨cases', h.1.symm⟩ + +set_option linter.unusedSimpArgs false in +/-- Source-lowered companion exposing the case-list lowering equation for a +singleton switch whose default is `revert(0,0)`. -/ +theorem lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered + (reservedNames : List String) (n0 : Nat) + (expr : YulExpr) (cases : List (Nat × List YulStmt)) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [YulStmt.switch expr cases + (some [YulStmt.expr (YulExpr.call "revert" + [YulExpr.lit 0, YulExpr.lit 0])])] = .ok (inner, next)) : + ∃ (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + inner = [Backends.lowerNativeSwitchBlock expr + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] ∧ + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) cases = + .ok (cases', midN) := by + rw [Backends.lowerStmtsNativeWithSwitchIds_cons, + Backends.lowerStmtGroupNativeWithSwitchIds_switch] at h + dsimp only [] at h + cases hCases : Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) cases with + | error _ => + rw [hCases] at h; simp only [Bind.bind, Except.bind, reduceCtorEq] at h + | ok casesPair => + obtain ⟨cases', midN⟩ := casesPair + rw [hCases] at h + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure] at h + rw [lowerStmtsNativeWithSwitchIds_revert_zero_zero] at h + simp only [Bind.bind, Except.bind, Pure.pure, Except.pure, + Backends.lowerStmtsNativeWithSwitchIds_nil, + List.singleton_append, Except.ok.injEq, Prod.mk.injEq] at h + exact ⟨cases', midN, h.1.symm, rfl⟩ + +/-- Generic native-lowering shape of the no-fallback/no-receive generated +dispatcher. + +This theorem peels the actual `buildSwitch funcs none none` source emitted by +codegen: the lowered inner block is the generated selector prologue, the +selector-miss default lowers to native `revert(0,0)`, and the selector-hit +switch is linked to the native lowering of the source case list emitted by +`buildSwitch`. -/ +theorem buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered + (funcs : List IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (h : Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) : + ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + inner = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some (Backends.lowerExprNative (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]] ∧ + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) := by + obtain ⟨_, hInner⟩ := lowerStmtsNative_block_stmts_eq _ _ h + obtain ⟨_, hLet, hRestLowering⟩ := + lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner + obtain ⟨body1', _, _, hIf1, _, hRest1⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering + obtain ⟨_, _, _, hIf2, hBody2, hRest2⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 + rw [Backends.lowerStmtsNativeWithSwitchIds_nil, + Except.ok.injEq, Prod.mk.injEq] at hRest2 + obtain ⟨hNil, _⟩ := hRest2 + subst hNil + obtain ⟨cases', midN, hBody2Eq, hLowerCases⟩ := + lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered + _ _ _ _ _ _ hBody2 + rw [hBody2Eq] at hIf2; rw [hIf2] at hIf1; rw [hIf1] at hLet + exact ⟨body1', _, _, cases', midN, hLet, hLowerCases⟩ + +/-- Reserved-context version of +`buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered`, used when the +generated dispatcher is lowered after helper functions have populated the +native runtime's reserved-name context. -/ +theorem buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered_withSwitchIds + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) : + ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + inner = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some (Backends.lowerExprNative (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]] ∧ + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) := by + have hInner := + lowerStmtsNativeWithSwitchIds_block_stmts_eq reservedNames n0 _ inner next h + obtain ⟨_, hLet, hRestLowering⟩ := + lowerStmtsNativeWithSwitchIds_let_head_eq _ _ _ _ _ _ _ hInner + obtain ⟨body1', _, _, hIf1, _, hRest1⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRestLowering + obtain ⟨_, _, _, hIf2, hBody2, hRest2⟩ := + lowerStmtsNativeWithSwitchIds_if_head_eq _ _ _ _ _ _ _ hRest1 + rw [Backends.lowerStmtsNativeWithSwitchIds_nil, + Except.ok.injEq, Prod.mk.injEq] at hRest2 + obtain ⟨hNil, _⟩ := hRest2 + subst hNil + obtain ⟨cases', midN, hBody2Eq, hLowerCases⟩ := + lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered + _ _ _ _ _ _ hBody2 + rw [hBody2Eq] at hIf2; rw [hIf2] at hIf1; rw [hIf1] at hLet + exact ⟨body1', _, cases', midN, hLet, hLowerCases⟩ + +/-- Selector-hit companion of +`buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered`: opening the +generated dispatcher lowering also lifts an `IRFunction` lookup hit through +the lowered native switch cases. -/ +theorem buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + (funcs : List IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (selector : Nat) (fn : IRFunction) + (h : Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) : + ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + inner = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some (Backends.lowerExprNative (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]] ∧ + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) := by + obtain ⟨body1, reservedNames, n0, cases', midN, hInner, hLowerCases⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered funcs inner h + obtain ⟨body', bodyStart, bodyEnd, hCase, hBodyLower⟩ := + lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_some_of_find_function + reservedNames (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + selector funcs fn cases' hLowerCases hFind + exact ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ + +/-- Reserved-context selector-hit companion of +`buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered_withSwitchIds`. -/ +theorem buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (selector : Nat) (fn : IRFunction) + (h : Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) : + ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + inner = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some (Backends.lowerExprNative (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]] ∧ + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) := by + obtain ⟨body1, switchStart, cases', midN, hInner, hLowerCases⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered_withSwitchIds + reservedNames n0 funcs inner next h + obtain ⟨body', bodyStart, bodyEnd, hCase, hBodyLower⟩ := + lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_some_of_find_function + reservedNames (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + selector funcs fn cases' hLowerCases hFind + exact ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ + +/-- Selector-miss companion of +`buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered`: opening the +generated dispatcher lowering also lifts an `IRFunction` lookup miss through +the lowered native switch cases. -/ +theorem buildSwitch_noFallback_noReceive_lowered_inner_find?_none_of_find_function + (funcs : List IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (selector : Nat) + (h : Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hFind : funcs.find? (fun f => f.selector == selector) = none) : + ∃ (body1 : List EvmYul.Yul.Ast.Stmt) (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)), + inner = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some (Backends.lowerExprNative (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]] ∧ + cases'.find? (fun entry => entry.1 == selector) = none := by + obtain ⟨body1, reservedNames, n0, cases', midN, hInner, hLowerCases⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered funcs inner h + have hCase := + lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function + reservedNames (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + selector funcs cases' hLowerCases hFind + exact ⟨body1, reservedNames, n0, cases', hInner, hCase⟩ + +theorem generatedRuntimeDispatcherHasNoFuncDefs_buildSwitch_noFallback_noReceive + (funcs : List IRFunction) + (hBodies : ∀ fn, fn ∈ funcs → yulStmtsContainFuncDef fn.body = false) : + generatedRuntimeDispatcherHasNoFuncDefs + [Compiler.CodegenCommon.buildSwitch funcs none none] = true := by + have hNoFunc : ∀ name params rets body, + Compiler.CodegenCommon.buildSwitch funcs none none ≠ + YulStmt.funcDef name params rets body := by + intro name params rets body h + simp [Compiler.CodegenCommon.buildSwitch] at h + rw [generatedRuntimeDispatcherHasNoFuncDefs_nonFunc_cons + (Compiler.CodegenCommon.buildSwitch funcs none none) [] hNoFunc] + simp [generatedRuntimeDispatcherHasNoFuncDefs, + buildSwitch_noFuncDefs_noFallback_noReceive funcs hBodies] + +theorem generatedRuntimeDispatcherHasNoFuncDefs_funcDef_prefix_append + (funcPrefix suffix : List YulStmt) + (hFuncDefs : ∀ stmt, stmt ∈ funcPrefix → + ∃ name params rets body, stmt = YulStmt.funcDef name params rets body) : + generatedRuntimeDispatcherHasNoFuncDefs (funcPrefix ++ suffix) = + generatedRuntimeDispatcherHasNoFuncDefs suffix := by + induction funcPrefix with + | nil => rfl + | cons stmt rest ih => + rcases hFuncDefs stmt (by simp) with ⟨name, params, rets, body, rfl⟩ + simp [ih (by + intro stmt hmem + exact hFuncDefs stmt (by simp [hmem]))] + +theorem generatedRuntimeDispatcherHasNoFuncDefs_runtimeCode_noFallback_noReceive + (contract : IRContract) + (hInternals : ∀ stmt, stmt ∈ contract.internalFunctions → + ∃ name params rets body, stmt = YulStmt.funcDef name params rets body) + (hBodies : ∀ fn, fn ∈ contract.functions → + yulStmtsContainFuncDef fn.body = false) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) : + generatedRuntimeDispatcherHasNoFuncDefs (Compiler.runtimeCode contract) = true := by + let runtimePrefix := + (if contract.usesMapping then [Compiler.mappingSlotFuncAt 0] else []) ++ + contract.internalFunctions + have hPrefix : + ∀ stmt, stmt ∈ runtimePrefix → + ∃ name params rets body, stmt = YulStmt.funcDef name params rets body := by + intro stmt hmem + simp only [runtimePrefix, List.mem_append] at hmem + rcases hmem with hMapping | hInternal + · split at hMapping <;> simp at hMapping + subst hMapping + exact ⟨"mappingSlot", ["baseSlot", "key"], ["slot"], _, rfl⟩ + · exact hInternals stmt hInternal + rw [Compiler.runtimeCode, Compiler.CodegenCommon.runtimeCode] + simp [hNoFallback, hNoReceive] + rw [← List.append_assoc] + change generatedRuntimeDispatcherHasNoFuncDefs + (runtimePrefix ++ [Compiler.CodegenCommon.buildSwitch contract.functions none none]) = + true + rw [generatedRuntimeDispatcherHasNoFuncDefs_funcDef_prefix_append runtimePrefix + [Compiler.CodegenCommon.buildSwitch contract.functions none none] hPrefix] + exact generatedRuntimeDispatcherHasNoFuncDefs_buildSwitch_noFallback_noReceive + contract.functions hBodies + +theorem generatedRuntimeDispatcherHasNoFuncDefs_emitYul_runtimeCode_noFallback_noReceive + (contract : IRContract) + (hInternals : ∀ stmt, stmt ∈ contract.internalFunctions → + ∃ name params rets body, stmt = YulStmt.funcDef name params rets body) + (hBodies : ∀ fn, fn ∈ contract.functions → + yulStmtsContainFuncDef fn.body = false) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) : + generatedRuntimeDispatcherHasNoFuncDefs + (Compiler.emitYul contract).runtimeCode = true := by + simpa [Compiler.emitYul, Compiler.CodegenCommon.emitYul] using + generatedRuntimeDispatcherHasNoFuncDefs_runtimeCode_noFallback_noReceive + contract hInternals hBodies hNoFallback hNoReceive + +theorem generatedRuntimeFunctionNamesUnique_append_nonFunc_suffix + (funcPrefix suffix : List YulStmt) + (hSuffix : ∀ stmt, stmt ∈ suffix → + ∀ name params rets body, stmt ≠ YulStmt.funcDef name params rets body) : + generatedRuntimeFunctionNamesUnique (funcPrefix ++ suffix) = + generatedRuntimeFunctionNamesUnique funcPrefix := by + simp [generatedRuntimeFunctionNamesUnique, + yulRuntimeTopLevelFunctionNames_eq_nil_of_all_nonFunc suffix hSuffix] + +theorem generatedRuntimeFunctionNamesUnique_buildSwitch_append + (funcPrefix : List YulStmt) + (funcs : List IRFunction) + (fallback : Option IREntrypoint) + (receive : Option IREntrypoint) : + generatedRuntimeFunctionNamesUnique + (funcPrefix ++ [Compiler.CodegenCommon.buildSwitch funcs fallback receive]) = + generatedRuntimeFunctionNamesUnique funcPrefix := by + apply generatedRuntimeFunctionNamesUnique_append_nonFunc_suffix + intro stmt hmem name params rets body h + simp only [List.mem_singleton] at hmem + subst hmem + cases fallback <;> cases receive <;> + simp [Compiler.CodegenCommon.buildSwitch] at h + +theorem generatedRuntimeFunctionNamesUnique_runtimeCode + (contract : IRContract) + (hPrefixUnique : generatedRuntimeFunctionNamesUnique + ((if contract.usesMapping then [Compiler.mappingSlotFuncAt 0] else []) ++ + contract.internalFunctions) = true) : + generatedRuntimeFunctionNamesUnique (Compiler.runtimeCode contract) = true := by + let runtimePrefix := + (if contract.usesMapping then [Compiler.mappingSlotFuncAt 0] else []) ++ + contract.internalFunctions + rw [Compiler.runtimeCode, Compiler.CodegenCommon.runtimeCode] + change generatedRuntimeFunctionNamesUnique + (runtimePrefix ++ [Compiler.CodegenCommon.buildSwitch contract.functions + contract.fallbackEntrypoint contract.receiveEntrypoint]) = true + rw [generatedRuntimeFunctionNamesUnique_buildSwitch_append] + exact hPrefixUnique + +theorem generatedRuntimeFunctionNamesUnique_emitYul_runtimeCode + (contract : IRContract) + (hPrefixUnique : generatedRuntimeFunctionNamesUnique + ((if contract.usesMapping then [Compiler.mappingSlotFuncAt 0] else []) ++ + contract.internalFunctions) = true) : + generatedRuntimeFunctionNamesUnique + (Compiler.emitYul contract).runtimeCode = true := by + simpa [Compiler.emitYul, Compiler.CodegenCommon.emitYul] using + generatedRuntimeFunctionNamesUnique_runtimeCode contract hPrefixUnique + +theorem mappingSlotFuncAt_body_noFuncDefs (scratchBase : Nat) : + yulStmtsContainFuncDef + (match Compiler.mappingSlotFuncAt scratchBase with + | YulStmt.funcDef _ _ _ body => body + | _ => []) = false := by + simp [Compiler.mappingSlotFuncAt, Compiler.CodegenCommon.mappingSlotFuncAt, + yulStmtContainsFuncDef, yulStmtsContainFuncDef] + +/-- Native EVMYulLean definition produced by lowering the generated +`mappingSlot` helper at scratch base zero. -/ +def nativeMappingSlotFunctionDefinition : EvmYul.Yul.Ast.FunctionDefinition := + EvmYul.Yul.Ast.FunctionDefinition.Def ["baseSlot", "key"] ["slot"] + [ .ExprStmtCall (.Call (.inl EvmYul.Operation.MSTORE) + [.Lit (EvmYul.UInt256.ofNat 0), .Var "key"]) + , .ExprStmtCall (.Call (.inl EvmYul.Operation.MSTORE) + [.Lit (EvmYul.UInt256.ofNat 32), .Var "baseSlot"]) + , .Let ["slot"] (some (.Call (.inl EvmYul.Operation.KECCAK256) + [.Lit (EvmYul.UInt256.ofNat 0), .Lit (EvmYul.UInt256.ofNat 64)])) + ] + +/-- The generated `mappingSlot` helper at scratch base zero lowers to the +corresponding native EVMYulLean helper function definition for any ambient +reserved-name set. -/ +theorem lowerFunctionDefinitionNativeWithReserved_mappingSlotFuncAt_zero + (globalReservedNames : List String) : + Backends.lowerFunctionDefinitionNativeWithReserved + globalReservedNames ["baseSlot", "key"] ["slot"] + (match Compiler.mappingSlotFuncAt 0 with + | YulStmt.funcDef _ _ _ body => body + | _ => []) = .ok nativeMappingSlotFunctionDefinition := by + simp [Backends.lowerFunctionDefinitionNativeWithReserved, + Compiler.mappingSlotFuncAt, Compiler.CodegenCommon.mappingSlotFuncAt, + Backends.lowerStmtsNativeWithSwitchIds, Backends.lowerExprNative, + Backends.lowerAssignNative, Backends.lookupRuntimePrimOp, + nativeMappingSlotFunctionDefinition, Bind.bind, Except.bind, Pure.pure, + Except.pure] + +/-- Body-form variant of +`lowerFunctionDefinitionNativeWithReserved_mappingSlotFuncAt_zero`, for proof +sites that have already unfolded the generated helper. -/ +theorem lowerFunctionDefinitionNativeWithReserved_mappingSlotFuncAt_zero_body + (globalReservedNames : List String) : + Backends.lowerFunctionDefinitionNativeWithReserved + globalReservedNames ["baseSlot", "key"] ["slot"] + [YulStmt.expr + (YulExpr.call "mstore" [YulExpr.lit 0, YulExpr.ident "key"]), + YulStmt.expr + (YulExpr.call "mstore" + [YulExpr.lit (0 + 32), YulExpr.ident "baseSlot"]), + YulStmt.assign "slot" + (YulExpr.call "keccak256" [YulExpr.lit 0, YulExpr.lit 64])] = + .ok nativeMappingSlotFunctionDefinition := by + simp [Backends.lowerFunctionDefinitionNativeWithReserved, + Backends.lowerStmtsNativeWithSwitchIds, Backends.lowerExprNative, + Backends.lowerAssignNative, Backends.lookupRuntimePrimOp, + nativeMappingSlotFunctionDefinition, Bind.bind, Except.bind, Pure.pure, + Except.pure] + +def nativeMappingSlotFunctionBody : List EvmYul.Yul.Ast.Stmt := + [ .ExprStmtCall (.Call (.inl EvmYul.Operation.MSTORE) + [.Lit (EvmYul.UInt256.ofNat 0), .Var "key"]) + , .ExprStmtCall (.Call (.inl EvmYul.Operation.MSTORE) + [.Lit (EvmYul.UInt256.ofNat 32), .Var "baseSlot"]) + , .Let ["slot"] (some (.Call (.inl EvmYul.Operation.KECCAK256) + [.Lit (EvmYul.UInt256.ofNat 0), .Lit (EvmYul.UInt256.ofNat 64)])) + ] + +theorem nativeMappingSlotFunctionDefinition_body : + nativeMappingSlotFunctionDefinition.body = nativeMappingSlotFunctionBody := by + rfl + +/-- Mapping-helper, no-internal/no-fallback/no-receive emitted runtimes lower +by first packaging the generated `mappingSlot` helper into the native function +map, then lowering the dispatcher in the full emitted-runtime reserved-name +context. -/ +theorem lowerRuntimeContractNative_emitYul_mapping_noInternals_noFallback_noReceive_reserved + (contract : IRContract) + (hMapping : contract.usesMapping = true) + (hInternals : contract.internalFunctions = []) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) : + Backends.lowerRuntimeContractNative (Compiler.emitYul contract).runtimeCode = + match Backends.lowerStmtsNativeWithSwitchIds + (Backends.yulStmtsIdentifierNames + (Compiler.emitYul contract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch contract.functions none none] with + | .ok (dispatcher, _) => + .ok { dispatcher := .Block dispatcher + functions := ((∅ : Backends.NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) } + | .error err => .error err := by + unfold Backends.lowerRuntimeContractNative + simp only [Compiler.emitYul, Compiler.CodegenCommon.emitYul, + Compiler.CodegenCommon.runtimeCode, hMapping, hInternals, hNoFallback, + hNoReceive, if_true] + simp only [List.singleton_append, List.append_nil] + simp only [Compiler.CodegenCommon.mappingSlotFuncAt] + rw [Backends.lowerRuntimeContractNativeAux_funcDef_cons_empty_of_lowerFunctionDefinition + (definition := nativeMappingSlotFunctionDefinition)] + · rw [lowerRuntimeContractNativeAux_single_stmt_eq_lowerStmtsNativeWithSwitchIds] + intro name params rets body h + simp [Compiler.CodegenCommon.buildSwitch] at h + · exact lowerFunctionDefinitionNativeWithReserved_mappingSlotFuncAt_zero_body _ + +/-- If mapping-helper emitted runtime lowering succeeds, the successful +contract is exactly the native dispatcher shell plus the generated native +`mappingSlot` helper. -/ +theorem lowerRuntimeContractNative_emitYul_mapping_ok_dispatcher_reserved + (contract : IRContract) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (hMapping : contract.usesMapping = true) + (hInternals : contract.internalFunctions = []) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) + (hLower : + Backends.lowerRuntimeContractNative (Compiler.emitYul contract).runtimeCode = + .ok nativeContract) : + ∃ (dispatcher : List EvmYul.Yul.Ast.Stmt) (nextSwitchId : Nat), + Backends.lowerStmtsNativeWithSwitchIds + (Backends.yulStmtsIdentifierNames + (Compiler.emitYul contract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch contract.functions none none] = + .ok (dispatcher, nextSwitchId) ∧ + nativeContract = + { dispatcher := .Block dispatcher + functions := ((∅ : Backends.NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) } := by + rw [lowerRuntimeContractNative_emitYul_mapping_noInternals_noFallback_noReceive_reserved + contract hMapping hInternals hNoFallback hNoReceive] at hLower + cases hDispatcher : + Backends.lowerStmtsNativeWithSwitchIds + (Backends.yulStmtsIdentifierNames (Compiler.emitYul contract).runtimeCode) + 0 [Compiler.CodegenCommon.buildSwitch contract.functions none none] with + | ok pair => + rcases pair with ⟨dispatcher, nextSwitchId⟩ + rw [hDispatcher] at hLower + simp only [Except.ok.injEq] at hLower + exact ⟨dispatcher, nextSwitchId, rfl, hLower.symm⟩ + | error err => + rw [hDispatcher] at hLower + simp at hLower + +theorem generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_append + (left right : List YulStmt) + (hLeft : generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs left = true) + (hRight : generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs right = true) : + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs (left ++ right) = true := by + induction left with + | nil => simpa using hRight + | cons stmt rest ih => + cases stmt <;> simp at hLeft ⊢ <;> try exact ih hLeft + case funcDef name params rets body => + exact ⟨hLeft.1, ih hLeft.2⟩ + +theorem generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_internalFunctions + (internals : List YulStmt) + (hBodies : ∀ name params rets body, + YulStmt.funcDef name params rets body ∈ internals → + yulStmtsContainFuncDef body = false) : + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs internals = true := by + induction internals with + | nil => rfl + | cons stmt rest ih => + have hRest : ∀ name params rets body, + YulStmt.funcDef name params rets body ∈ rest → + yulStmtsContainFuncDef body = false := by + intro name params rets body hmem + exact hBodies name params rets body (by simp [hmem]) + cases stmt <;> simp [ih hRest] + case funcDef name params rets body => + exact hBodies name params rets body (by simp) + +theorem generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_buildSwitch + (funcs : List IRFunction) + (fallback : Option IREntrypoint) + (receive : Option IREntrypoint) : + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs + [Compiler.CodegenCommon.buildSwitch funcs fallback receive] = true := by + have hNoFunc : ∀ name params rets body, + Compiler.CodegenCommon.buildSwitch funcs fallback receive ≠ + YulStmt.funcDef name params rets body := by + intro name params rets body h + cases fallback <;> cases receive <;> + simp [Compiler.CodegenCommon.buildSwitch] at h + rw [generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_nonFunc_cons + (Compiler.CodegenCommon.buildSwitch funcs fallback receive) [] hNoFunc] + rfl + +theorem generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_runtimeCode + (contract : IRContract) + (hInternalBodies : ∀ name params rets body, + YulStmt.funcDef name params rets body ∈ contract.internalFunctions → + yulStmtsContainFuncDef body = false) : + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs + (Compiler.runtimeCode contract) = true := by + let mapping := if contract.usesMapping then [Compiler.mappingSlotFuncAt 0] else [] + have hMapping : + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs mapping = true := by + by_cases hUsesMapping : contract.usesMapping + · simp [mapping, hUsesMapping, generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs, + Compiler.mappingSlotFuncAt, Compiler.CodegenCommon.mappingSlotFuncAt, + yulFunctionBodies, yulStmtContainsFuncDef, yulStmtsContainFuncDef] + · simp [mapping, hUsesMapping, generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs] + have hInternals : + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs + contract.internalFunctions = true := + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_internalFunctions + contract.internalFunctions hInternalBodies + have hSwitch : + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs + [Compiler.CodegenCommon.buildSwitch contract.functions + contract.fallbackEntrypoint contract.receiveEntrypoint] = true := + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_buildSwitch + contract.functions contract.fallbackEntrypoint contract.receiveEntrypoint + rw [Compiler.runtimeCode, Compiler.CodegenCommon.runtimeCode] + change generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs + (mapping ++ contract.internalFunctions ++ + [Compiler.CodegenCommon.buildSwitch contract.functions + contract.fallbackEntrypoint contract.receiveEntrypoint]) = true + rw [List.append_assoc] + exact generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_append + mapping (contract.internalFunctions ++ + [Compiler.CodegenCommon.buildSwitch contract.functions + contract.fallbackEntrypoint contract.receiveEntrypoint]) + hMapping + (generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_append + contract.internalFunctions + [Compiler.CodegenCommon.buildSwitch contract.functions + contract.fallbackEntrypoint contract.receiveEntrypoint] + hInternals hSwitch) + +theorem generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_emitYul_runtimeCode + (contract : IRContract) + (hInternalBodies : ∀ name params rets body, + YulStmt.funcDef name params rets body ∈ contract.internalFunctions → + yulStmtsContainFuncDef body = false) : + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs + (Compiler.emitYul contract).runtimeCode = true := by + simpa [Compiler.emitYul, Compiler.CodegenCommon.emitYul] using + generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_runtimeCode + contract hInternalBodies + /-- Executable characterization for the generated runtime shape that the native EVMYulLean lowering path currently accepts: top-level `funcDef` statements are helpers, dispatcher statements contain no nested function @@ -233,6 +2314,30 @@ def generatedRuntimeNativeFragment (runtimeCode : List YulStmt) : Bool := generatedRuntimeDispatcherHasNoFuncDefs runtimeCode && generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs runtimeCode +theorem generatedRuntimeNativeFragment_emitYul_runtimeCode_noFallback_noReceive + (contract : IRContract) + (hPrefixUnique : generatedRuntimeFunctionNamesUnique + ((if contract.usesMapping then [Compiler.mappingSlotFuncAt 0] else []) ++ + contract.internalFunctions) = true) + (hInternals : ∀ stmt, stmt ∈ contract.internalFunctions → + ∃ name params rets body, stmt = YulStmt.funcDef name params rets body) + (hExternalBodies : ∀ fn, fn ∈ contract.functions → + yulStmtsContainFuncDef fn.body = false) + (hInternalBodies : ∀ name params rets body, + YulStmt.funcDef name params rets body ∈ contract.internalFunctions → + yulStmtsContainFuncDef body = false) + (hNoFallback : contract.fallbackEntrypoint = none) + (hNoReceive : contract.receiveEntrypoint = none) : + generatedRuntimeNativeFragment (Compiler.emitYul contract).runtimeCode = true := by + have hNames := generatedRuntimeFunctionNamesUnique_emitYul_runtimeCode + contract hPrefixUnique + have hDispatcher := + generatedRuntimeDispatcherHasNoFuncDefs_emitYul_runtimeCode_noFallback_noReceive + contract hInternals hExternalBodies hNoFallback hNoReceive + have hBodies := generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_emitYul_runtimeCode + contract hInternalBodies + simp [generatedRuntimeNativeFragment, hNames, hDispatcher, hBodies] + def unsupportedGeneratedRuntimeNativeFragmentError : AdapterError := "native EVMYulLean generated runtime fragment check failed" @@ -375,7 +2480,8 @@ def nativeRuntimePathUsesBuiltin (yulFunctionBodies runtimeCode) runtimeCode def unsupportedNativeHeaderBuiltinNames : List String := - ["coinbase", "difficulty", "prevrandao", "gaslimit", "basefee", "gasprice"] + ["coinbase", "difficulty", "prevrandao", "gaslimit", "basefee", "gasprice", + "selfbalance"] def nativeRuntimePathUsesAnyBuiltin (builtins : List String) @@ -405,8 +2511,8 @@ def unsupportedNativeChainIdError : AdapterError := current bridge supports only EVMYulLean global chain id" def unsupportedNativeHeaderBuiltinError : AdapterError := - "native EVMYulLean selected runtime path uses a header builtin that is not \ - represented in Verity's YulTransaction bridge" + "native EVMYulLean selected runtime path uses a header/account builtin that \ + is not represented in Verity's YulTransaction bridge" def validateNativeRuntimeEnvironment (runtimeCode : List YulStmt) @@ -463,6 +2569,34 @@ def validateNativeRuntimeEnvironment validateNativeRuntimeEnvironment runtimeCode tx = .ok () := by simp [validateNativeRuntimeEnvironment, hChainId, hBlobBaseFee, hNoHeader] +@[simp] theorem validateNativeRuntimeEnvironment_ofIR_representableEnvironment + (runtimeCode : List YulStmt) + (tx : IRTransaction) + (hChainId : nativeChainIdRepresentable tx.chainId = true) + (hBlobBaseFee : nativeBlobBaseFeeRepresentable tx.blobBaseFee = true) + (hNoHeader : + nativeRuntimePathUsesUnsupportedHeaderBuiltin runtimeCode + (YulTransaction.ofIR tx) = false) : + validateNativeRuntimeEnvironment runtimeCode (YulTransaction.ofIR tx) = + .ok () := by + simpa [YulTransaction.ofIR] using + validateNativeRuntimeEnvironment_representableEnvironment + runtimeCode (YulTransaction.ofIR tx) hChainId hBlobBaseFee hNoHeader + +@[simp] theorem validateNativeRuntimeEnvironment_ofIR_globalDefaults + (runtimeCode : List YulStmt) + (tx : IRTransaction) + (hChainId : tx.chainId = EvmYul.chainId) + (hBlobBaseFee : tx.blobBaseFee = EvmYul.MIN_BASE_FEE_PER_BLOB_GAS) + (hNoHeader : + nativeRuntimePathUsesUnsupportedHeaderBuiltin runtimeCode + (YulTransaction.ofIR tx) = false) : + validateNativeRuntimeEnvironment runtimeCode (YulTransaction.ofIR tx) = + .ok () := by + simpa [YulTransaction.ofIR, hChainId, hBlobBaseFee] using + validateNativeRuntimeEnvironment_ofIR_representableEnvironment + runtimeCode tx (by simp [hChainId]) (by simp [hBlobBaseFee]) hNoHeader + @[simp] theorem validateNativeRuntimeEnvironment_unsupportedChainId (runtimeCode : List YulStmt) (tx : YulTransaction) @@ -666,38 +2800,53 @@ theorem readBytes_zero_get?_of_lt_source · simp [ByteArray.get] · contradiction -/-- Reading the ABI word at calldata offset four preserves each source byte - already present in that 32-byte argument window. This is the native - `calldataload(4)` byte-level counterpart of - `readBytes_zero_get?_of_lt_source`. -/ -theorem readBytes_offset4_get?_of_lt_source +/-- Reading a 32-byte window preserves every byte that is already present in the + source window, for offsets accepted by EVMYulLean's optimized + `ByteArray.readBytes` branch. -/ +theorem readBytes_get?_of_lt_source (source : ByteArray) - (i : Nat) - (hi : 4 + i < source.size) + (offset i : Nat) + (hoffset : offset < 2 ^ 64) + (hi : offset + i < source.size) (hi32 : i < 32) : - (ByteArray.readBytes source 4 32).get? i = source.get? (4 + i) := by + (ByteArray.readBytes source offset 32).get? i = + source.get? (offset + i) := by unfold ByteArray.readBytes - have hsmall : (decide (4 < 2 ^ 64) && decide (32 < 2 ^ 64)) = true := by - norm_num + have hoffset' : offset < 18446744073709551616 := by + simpa using hoffset + have hsmall : (decide (offset < 2 ^ 64) && decide (32 < 2 ^ 64)) = true := by + simp [hoffset'] simp only [hsmall, ↓reduceIte] - have hiData : 4 + i < source.data.size := by + have hiData : offset + i < source.data.size := by simpa using hi - have hCopySize : i < (source.copySlice 4 ByteArray.empty 0 32).size := by + have hCopySize : i < (source.copySlice offset ByteArray.empty 0 32).size := by simp [ByteArray.size, ByteArray.data_copySlice] omega calc - (source.copySlice 4 ByteArray.empty 0 32 ++ + (source.copySlice offset ByteArray.empty 0 32 ++ ffi.ByteArray.zeroes { toBitVec := ↑32 - - ↑(source.copySlice 4 ByteArray.empty 0 32).size }).get? i - = (source.copySlice 4 ByteArray.empty 0 32).get? i := + ↑(source.copySlice offset ByteArray.empty 0 32).size }).get? i + = (source.copySlice offset ByteArray.empty 0 32).get? i := byteArray_get?_append_left hCopySize - _ = source.get? (4 + i) := by + _ = source.get? (offset + i) := by unfold ByteArray.get? split · simp [ByteArray.get] · contradiction +/-- Reading the ABI word at calldata offset four preserves each source byte + already present in that 32-byte argument window. This is the native + `calldataload(4)` byte-level counterpart of + `readBytes_zero_get?_of_lt_source`. -/ +theorem readBytes_offset4_get?_of_lt_source + (source : ByteArray) + (i : Nat) + (hi : 4 + i < source.size) + (hi32 : i < 32) : + (ByteArray.readBytes source 4 32).get? i = source.get? (4 + i) := by + exact readBytes_get?_of_lt_source source 4 i (by norm_num) hi hi32 + @[simp] theorem initialState_calldataReadWord_selectorByte0 (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) @@ -831,6 +2980,44 @@ theorem initialState_calldataReadWord_arg0Byte omega · exact hi +/-- Native initial calldata exposes any aligned ABI argument word byte-for-byte + when the argument is present and the read offset stays in the optimized + `ByteArray.readBytes` range. -/ +theorem initialState_calldataReadWord_argByte_of_drop_eq_cons + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (idx arg : Nat) + (rest : List Nat) + (hdrop : tx.args.drop idx = arg :: rest) + (hoffset : 4 + 32 * idx < 2 ^ 64) + (i : Nat) + (hi : i < 32) : + (ByteArray.readBytes + (initialState contract tx storage observableSlots).toState.executionEnv.calldata + (4 + 32 * idx) 32).get? i = + some (UInt8.ofNat (arg / 2 ^ ((31 - i) * 8) % 256)) := by + rw [readBytes_get?_of_lt_source] + · rw [show + (initialState contract tx storage observableSlots).toState.executionEnv.calldata = + calldataToByteArray tx.functionSelector tx.args by + simp [initialState, EvmYul.Yul.State.toState, YulState.initial, + toSharedState, mkBlockHeader]] + exact calldataToByteArray_argByte_of_drop_eq_cons tx.functionSelector + tx.args idx arg rest hdrop i hi + · exact hoffset + · rw [show + (initialState contract tx storage observableSlots).toState.executionEnv.calldata = + calldataToByteArray tx.functionSelector tx.args by + simp [initialState, EvmYul.Yul.State.toState, YulState.initial, + toSharedState, mkBlockHeader]] + simp [calldataToByteArray_size] + have hlen := congrArg List.length hdrop + simp [List.length_drop] at hlen + omega + · exact hi + private theorem byteArray_data_toList_get?_of_get? (ba : ByteArray) (i : Nat) @@ -905,7 +3092,7 @@ theorem initialState_calldataReadWord_selectorPrefix /-- Recompose the four ABI selector bytes into the normalized 32-bit dispatcher selector. This isolates the remaining native byte-decoding proof: once `calldataload(0) >>> 224` is reduced to the four high calldata bytes, - this theorem closes the arithmetic side against the interpreter oracle. -/ + this theorem closes the arithmetic side against the EVMYulLean fuel wrapper. -/ theorem selectorBytesAsNat (selector : Nat) : (selector / 2^24 % 256) * 2^24 + (selector / 2^16 % 256) * 2^16 + @@ -1183,11 +3370,14 @@ theorem readBytes_zero_32_size (source : ByteArray) : · omega · omega -theorem readBytes_offset4_32_size (source : ByteArray) : - (ByteArray.readBytes source 4 32).size = 32 := by +theorem readBytes_32_size (source : ByteArray) (offset : Nat) + (hoffset : offset < 2 ^ 64) : + (ByteArray.readBytes source offset 32).size = 32 := by unfold ByteArray.readBytes - have hsmall : (decide (4 < 2 ^ 64) && decide (32 < 2 ^ 64)) = true := by - norm_num + have hoffset' : offset < 18446744073709551616 := by + simpa using hoffset + have hsmall : (decide (offset < 2 ^ 64) && decide (32 < 2 ^ 64)) = true := by + simp [hoffset'] simp only [hsmall, ↓reduceIte] rw [ByteArray.size_append] simp [ffi.ByteArray.zeroes, ByteArray.size] @@ -1195,6 +3385,10 @@ theorem readBytes_offset4_32_size (source : ByteArray) : · omega · omega +theorem readBytes_offset4_32_size (source : ByteArray) : + (ByteArray.readBytes source 4 32).size = 32 := by + exact readBytes_32_size source 4 (by norm_num) + theorem readWithPadding_32_size (source : ByteArray) (addr : Nat) : (source.readWithPadding addr 32).size = 32 := by unfold ByteArray.readWithPadding @@ -1385,6 +3579,54 @@ theorem initialState_calldataReadWord_arg0Bytes exact List.getElem?_eq_none (by simp; omega) rw [hleft, hright] +/-- Native `readBytes` returns the exact 32-byte big-endian representation of + any present aligned ABI argument word. -/ +theorem initialState_calldataReadWord_argBytes_of_drop_eq_cons + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (idx arg : Nat) + (rest : List Nat) + (hdrop : tx.args.drop idx = arg :: rest) + (hoffset : 4 + 32 * idx < 2 ^ 64) : + let bytes := ByteArray.readBytes + (initialState contract tx storage observableSlots).toState.executionEnv.calldata + (4 + 32 * idx) 32 + bytes.data.toList = + List.ofFn (fun i : Fin 32 => + UInt8.ofNat (arg / 2 ^ ((31 - i.1) * 8) % 256)) := by + intro bytes + apply List.ext_getElem? + intro i + by_cases hi : i < 32 + · have hleft : bytes.data.toList[i]? = + some (UInt8.ofNat (arg / 2 ^ ((31 - i) * 8) % 256)) := by + exact byteArray_data_toList_get?_of_get? bytes i _ + (by + dsimp [bytes] + exact initialState_calldataReadWord_argByte_of_drop_eq_cons + contract tx storage observableSlots idx arg rest hdrop hoffset i hi) + have hright : + (List.ofFn (fun i : Fin 32 => + UInt8.ofNat (arg / 2 ^ ((31 - i.1) * 8) % 256)))[i]? = + some (UInt8.ofNat (arg / 2 ^ ((31 - i) * 8) % 256)) := by + rw [List.getElem?_ofFn] + simp only [hi, ↓reduceDIte] + rw [hleft, hright] + · have hleft : bytes.data.toList[i]? = none := by + have hlen : bytes.data.toList.length = 32 := by + have hsize := readBytes_32_size + (initialState contract tx storage observableSlots).toState.executionEnv.calldata + (4 + 32 * idx) hoffset + simpa [bytes, ByteArray.size] using hsize + exact List.getElem?_eq_none (by omega) + have hright : + (List.ofFn (fun i : Fin 32 => + UInt8.ofNat (arg / 2 ^ ((31 - i.1) * 8) % 256)))[i]? = none := by + exact List.getElem?_eq_none (by simp; omega) + rw [hleft, hright] + /-- Native `calldataload(4)` decodes the first aligned ABI argument word from the bridged calldata exactly as a `UInt256`, i.e. modulo the EVM word size. -/ theorem initialState_calldataload4_arg0_value @@ -1447,6 +3689,73 @@ theorem initialState_calldataload4_arg0_word (Fin.ofNat EvmYul.UInt256.size arg).val simp [Fin.ofNat] +/-- Native `calldataload(4 + 32*idx)` decodes a present aligned ABI argument + word from bridged calldata exactly as a `UInt256`, modulo the EVM word + size. -/ +theorem initialState_calldataload_aligned_arg_value + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (idx arg : Nat) + (rest : List Nat) + (hdrop : tx.args.drop idx = arg :: rest) + (hoffset : 4 + 32 * idx < 2 ^ 64) : + EvmYul.UInt256.toNat + (EvmYul.State.calldataload + (initialState contract tx storage observableSlots).toState + (EvmYul.UInt256.ofNat (4 + 32 * idx))) = + arg % EvmYul.UInt256.size := by + let bytes := ByteArray.readBytes + (initialState contract tx storage observableSlots).toState.executionEnv.calldata + (4 + 32 * idx) 32 + have hbytes := + initialState_calldataReadWord_argBytes_of_drop_eq_cons contract tx storage + observableSlots idx arg rest hdrop hoffset + have hoffset256 : 4 + 32 * idx < EvmYul.UInt256.size := by + have h64 : 2 ^ 64 < EvmYul.UInt256.size := by + norm_num [EvmYul.UInt256.size] + exact Nat.lt_trans hoffset h64 + unfold EvmYul.State.calldataload EvmYul.uInt256OfByteArray + rw [uint256_ofNat_toNat_of_lt (4 + 32 * idx) hoffset256] + rw [show + (ByteArray.readBytes + (initialState contract tx storage observableSlots).toState.executionEnv.calldata + (4 + 32 * idx) 32).data.toList = + bytes.data.toList by rfl] + rw [hbytes] + change EvmYul.UInt256.toNat + (EvmYul.UInt256.ofNat + (EvmYul.fromBytes' + ((List.ofFn fun i : Fin 32 => + UInt8.ofNat (arg / 2 ^ ((31 - i.1) * 8) % 256)).reverse))) = + arg % EvmYul.UInt256.size + rw [fromBytes'_argWordBytes arg] + exact uint256_ofNat_toNat_of_lt (arg % EvmYul.UInt256.size) + (Nat.mod_lt _ (by norm_num [EvmYul.UInt256.size])) + +/-- Native `calldataload(4 + 32*idx)` decodes a present aligned ABI argument + as the exact EVM word used by the state bridge. -/ +theorem initialState_calldataload_aligned_arg_word + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (idx arg : Nat) + (rest : List Nat) + (hdrop : tx.args.drop idx = arg :: rest) + (hoffset : 4 + 32 * idx < 2 ^ 64) : + EvmYul.State.calldataload + (initialState contract tx storage observableSlots).toState + (EvmYul.UInt256.ofNat (4 + 32 * idx)) = + natToUInt256 arg := by + apply uint256_eq_of_toNat_eq + rw [initialState_calldataload_aligned_arg_value contract tx storage + observableSlots idx arg rest hdrop hoffset] + change arg % EvmYul.UInt256.size = + (Fin.ofNat EvmYul.UInt256.size arg).val + simp [Fin.ofNat] + /-- Native selector decoding agrees with the interpreter selector by reducing EVMYulLean `calldataload(0) >>> 224` to the four ABI selector bytes in the initial bridged calldata. -/ @@ -1625,15 +3934,36 @@ theorem lowerExprNative_selectorExpr : .ok (state, some (EvmYul.UInt256.ofNat state.executionEnv.calldata.size)) := by rfl +theorem step_calldatasize_any + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.CALLDATASIZE none state values = + .ok (state, some (EvmYul.UInt256.ofNat state.executionEnv.calldata.size)) := by + rfl + @[simp] theorem step_callvalue_ok (state : EvmYul.Yul.State) : EvmYul.step (τ := .Yul) EvmYul.Operation.CALLVALUE none state [] = .ok (state, some state.executionEnv.weiValue) := by rfl -@[simp] theorem step_address_ok - (state : EvmYul.Yul.State) : - EvmYul.step (τ := .Yul) EvmYul.Operation.ADDRESS none state [] = +theorem step_callvalue_any + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.CALLVALUE none state values = + .ok (state, some state.executionEnv.weiValue) := by + rfl + +@[simp] theorem step_address_ok + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.ADDRESS none state [] = + .ok (state, some (EvmYul.UInt256.ofNat state.executionEnv.codeOwner.val)) := by + rfl + +theorem step_address_any + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.ADDRESS none state values = .ok (state, some (EvmYul.UInt256.ofNat state.executionEnv.codeOwner.val)) := by rfl @@ -1658,30 +3988,65 @@ theorem lowerExprNative_selectorExpr : .ok (state, some (EvmYul.UInt256.ofNat state.executionEnv.source.val)) := by rfl +theorem step_caller_any + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.CALLER none state values = + .ok (state, some (EvmYul.UInt256.ofNat state.executionEnv.source.val)) := by + rfl + @[simp] theorem step_timestamp_ok (state : EvmYul.Yul.State) : EvmYul.step (τ := .Yul) EvmYul.Operation.TIMESTAMP none state [] = .ok (state, some state.toState.timeStamp) := by rfl +theorem step_timestamp_any + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.TIMESTAMP none state values = + .ok (state, some state.toState.timeStamp) := by + rfl + @[simp] theorem step_number_ok (state : EvmYul.Yul.State) : EvmYul.step (τ := .Yul) EvmYul.Operation.NUMBER none state [] = .ok (state, some state.toState.number) := by rfl +theorem step_number_any + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.NUMBER none state values = + .ok (state, some state.toState.number) := by + rfl + @[simp] theorem step_chainid_ok (state : EvmYul.Yul.State) : EvmYul.step (τ := .Yul) EvmYul.Operation.CHAINID none state [] = .ok (state, some state.toState.chainId) := by rfl +theorem step_chainid_any + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.CHAINID none state values = + .ok (state, some state.toState.chainId) := by + rfl + @[simp] theorem step_blobbasefee_ok (state : EvmYul.Yul.State) : EvmYul.step (τ := .Yul) EvmYul.Operation.BLOBBASEFEE none state [] = .ok (state, some state.executionEnv.getBlobGasprice) := by rfl +theorem step_blobbasefee_any + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.BLOBBASEFEE none state values = + .ok (state, some state.executionEnv.getBlobGasprice) := by + rfl + @[simp] theorem step_gasprice_ok (state : EvmYul.Yul.State) : EvmYul.step (τ := .Yul) EvmYul.Operation.GASPRICE none state [] = @@ -1721,6 +4086,28 @@ theorem lowerExprNative_selectorExpr : none) := by rfl +theorem step_mstore_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.MSTORE none state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mstore_singleton_invalid + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.MSTORE none state [offset] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mstore_overarity_invalid + (state : EvmYul.Yul.State) + (offset value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.MSTORE none state + (offset :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem step_mstore8_ok (state : EvmYul.Yul.State) (offset value : EvmYul.UInt256) : @@ -1729,6 +4116,28 @@ theorem lowerExprNative_selectorExpr : none) := by rfl +theorem step_mstore8_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.MSTORE8 none state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mstore8_singleton_invalid + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.MSTORE8 none state [offset] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mstore8_overarity_invalid + (state : EvmYul.Yul.State) + (offset value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.MSTORE8 none state + (offset :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem step_sload_ok (state : EvmYul.Yul.State) (slot : EvmYul.UInt256) : @@ -1754,6 +4163,28 @@ theorem lowerExprNative_selectorExpr : .ok (state.setMachineState machineState', some value) := by rfl +@[simp] theorem step_log0_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG0 none state [] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log0_singleton_invalid + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG0 none state [offset] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log0_overarity_invalid + (state : EvmYul.Yul.State) + (offset size extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG0 none state + (offset :: size :: extra :: rest) = + Except.ok (state, none) := by + rfl + @[simp] theorem step_log0_ok (state : EvmYul.Yul.State) (offset size : EvmYul.UInt256) : @@ -1762,6 +4193,35 @@ theorem lowerExprNative_selectorExpr : (EvmYul.SharedState.logOp offset size #[] state.toSharedState), none) := by rfl +@[simp] theorem step_log1_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG1 none state [] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log1_singleton_invalid + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG1 none state [offset] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log1_pair_invalid + (state : EvmYul.Yul.State) + (offset size : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG1 none state [offset, size] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log1_overarity_invalid + (state : EvmYul.Yul.State) + (offset size topic0 extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG1 none state + (offset :: size :: topic0 :: extra :: rest) = + Except.ok (state, none) := by + rfl + @[simp] theorem step_log1_ok (state : EvmYul.Yul.State) (offset size topic0 : EvmYul.UInt256) : @@ -1771,6 +4231,43 @@ theorem lowerExprNative_selectorExpr : (EvmYul.SharedState.logOp offset size #[topic0] state.toSharedState), none) := by rfl +@[simp] theorem step_log2_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG2 none state [] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log2_singleton_invalid + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG2 none state [offset] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log2_pair_invalid + (state : EvmYul.Yul.State) + (offset size : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG2 none state [offset, size] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log2_triple_invalid + (state : EvmYul.Yul.State) + (offset size topic0 : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG2 none state + [offset, size, topic0] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log2_overarity_invalid + (state : EvmYul.Yul.State) + (offset size topic0 topic1 extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG2 none state + (offset :: size :: topic0 :: topic1 :: extra :: rest) = + Except.ok (state, none) := by + rfl + @[simp] theorem step_log2_ok (state : EvmYul.Yul.State) (offset size topic0 topic1 : EvmYul.UInt256) : @@ -1781,6 +4278,51 @@ theorem lowerExprNative_selectorExpr : state.toSharedState), none) := by rfl +@[simp] theorem step_log3_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG3 none state [] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log3_singleton_invalid + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG3 none state [offset] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log3_pair_invalid + (state : EvmYul.Yul.State) + (offset size : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG3 none state [offset, size] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log3_triple_invalid + (state : EvmYul.Yul.State) + (offset size topic0 : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG3 none state + [offset, size, topic0] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log3_quad_invalid + (state : EvmYul.Yul.State) + (offset size topic0 topic1 : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG3 none state + [offset, size, topic0, topic1] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log3_overarity_invalid + (state : EvmYul.Yul.State) + (offset size topic0 topic1 topic2 extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG3 none state + (offset :: size :: topic0 :: topic1 :: topic2 :: extra :: rest) = + Except.ok (state, none) := by + rfl + @[simp] theorem step_log3_ok (state : EvmYul.Yul.State) (offset size topic0 topic1 topic2 : EvmYul.UInt256) : @@ -1791,6 +4333,59 @@ theorem lowerExprNative_selectorExpr : state.toSharedState), none) := by rfl +@[simp] theorem step_log4_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG4 none state [] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log4_singleton_invalid + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG4 none state [offset] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log4_pair_invalid + (state : EvmYul.Yul.State) + (offset size : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG4 none state [offset, size] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log4_triple_invalid + (state : EvmYul.Yul.State) + (offset size topic0 : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG4 none state + [offset, size, topic0] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log4_quad_invalid + (state : EvmYul.Yul.State) + (offset size topic0 topic1 : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG4 none state + [offset, size, topic0, topic1] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log4_quint_invalid + (state : EvmYul.Yul.State) + (offset size topic0 topic1 topic2 : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG4 none state + [offset, size, topic0, topic1, topic2] = + Except.ok (state, none) := by + rfl + +@[simp] theorem step_log4_overarity_invalid + (state : EvmYul.Yul.State) + (offset size topic0 topic1 topic2 topic3 extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.LOG4 none state + (offset :: size :: topic0 :: topic1 :: topic2 :: topic3 :: extra :: rest) = + Except.ok (state, none) := by + rfl + @[simp] theorem step_log4_ok (state : EvmYul.Yul.State) (offset size topic0 topic1 topic2 topic3 : EvmYul.UInt256) : @@ -1808,6 +4403,28 @@ theorem lowerExprNative_selectorExpr : .ok (state.setState (state.toState.sstore slot value), none) := by rfl +theorem step_sstore_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.SSTORE none state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sstore_singleton_invalid + (state : EvmYul.Yul.State) + (slot : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.SSTORE none state [slot] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sstore_overarity_invalid + (state : EvmYul.Yul.State) + (slot value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.SSTORE none state + (slot :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem step_tload_ok (state : EvmYul.Yul.State) (slot : EvmYul.UInt256) : @@ -1824,6 +4441,28 @@ theorem lowerExprNative_selectorExpr : .ok (state.setState (state.toState.tstore slot value), none) := by rfl +theorem step_tstore_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.TSTORE none state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_tstore_singleton_invalid + (state : EvmYul.Yul.State) + (slot : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.TSTORE none state [slot] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_tstore_overarity_invalid + (state : EvmYul.Yul.State) + (slot value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.TSTORE none state + (slot :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem step_msize_ok (state : EvmYul.Yul.State) : EvmYul.step (τ := .Yul) EvmYul.Operation.MSIZE none state [] = @@ -1851,6 +4490,37 @@ theorem lowerExprNative_selectorExpr : (state.toSharedState.calldatacopy mstart datastart size), none) := by rfl +theorem step_calldatacopy_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.CALLDATACOPY none state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_calldatacopy_singleton_invalid + (state : EvmYul.Yul.State) + (mstart : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.CALLDATACOPY none state + [mstart] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_calldatacopy_pair_invalid + (state : EvmYul.Yul.State) + (mstart datastart : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.CALLDATACOPY none state + [mstart, datastart] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_calldatacopy_overarity_invalid + (state : EvmYul.Yul.State) + (mstart datastart size extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.CALLDATACOPY none state + (mstart :: datastart :: size :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem step_returndatacopy_ok (state : EvmYul.Yul.State) (mstart rstart size : EvmYul.UInt256) : @@ -1861,6 +4531,37 @@ theorem lowerExprNative_selectorExpr : none) := by rfl +theorem step_returndatacopy_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.RETURNDATACOPY none state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_returndatacopy_singleton_invalid + (state : EvmYul.Yul.State) + (mstart : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.RETURNDATACOPY none state + [mstart] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_returndatacopy_pair_invalid + (state : EvmYul.Yul.State) + (mstart rstart : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.RETURNDATACOPY none state + [mstart, rstart] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_returndatacopy_overarity_invalid + (state : EvmYul.Yul.State) + (mstart rstart size extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.RETURNDATACOPY none state + (mstart :: rstart :: size :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem step_pop_ok (state : EvmYul.Yul.State) (value : EvmYul.UInt256) : @@ -1885,6 +4586,28 @@ theorem lowerExprNative_selectorExpr : .error (EvmYul.Yul.Exception.YulHalt s (value.getD ⟨1⟩)) := by rfl +theorem step_return_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.RETURN none state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_return_singleton_invalid + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.RETURN none state [offset] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_return_overarity_invalid + (state : EvmYul.Yul.State) + (offset size extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.RETURN none state + (offset :: size :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem step_revert_ok (state : EvmYul.Yul.State) (offset size : EvmYul.UInt256) : @@ -1895,6 +4618,28 @@ theorem lowerExprNative_selectorExpr : | .ok (_, _) => .error EvmYul.Yul.Exception.Revert := by rfl +theorem step_revert_nil_invalid + (state : EvmYul.Yul.State) : + EvmYul.step (τ := .Yul) EvmYul.Operation.REVERT none state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_revert_singleton_invalid + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.REVERT none state [offset] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_revert_overarity_invalid + (state : EvmYul.Yul.State) + (offset size extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.step (τ := .Yul) EvmYul.Operation.REVERT none state + (offset :: size :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem primCall_calldataload_ok (fuel : Nat) (shared : EvmYul.SharedState .Yul) @@ -2000,6 +4745,28 @@ theorem primCall_calldataload4_initialState_ofIR_arg0_ok_withStore .ok (state, [EvmYul.UInt256.add left right]) := by cases fuel <;> simp [EvmYul.Yul.primCall] +theorem step_add_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.ADD none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_add_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.ADD none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_add_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.ADD none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem primCall_sub_ok (fuel : Nat) (state : EvmYul.Yul.State) @@ -2009,6 +4776,28 @@ theorem primCall_calldataload4_initialState_ofIR_arg0_ok_withStore .ok (state, [EvmYul.UInt256.sub left right]) := by cases fuel <;> simp [EvmYul.Yul.primCall] +theorem step_sub_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SUB none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sub_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SUB none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sub_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SUB none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem primCall_mul_ok (fuel : Nat) (state : EvmYul.Yul.State) @@ -2018,6 +4807,28 @@ theorem primCall_calldataload4_initialState_ofIR_arg0_ok_withStore .ok (state, [EvmYul.UInt256.mul left right]) := by cases fuel <;> simp [EvmYul.Yul.primCall] +theorem step_mul_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MUL none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mul_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MUL none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mul_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MUL none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + @[simp] theorem primCall_div_ok (fuel : Nat) (state : EvmYul.Yul.State) @@ -2027,8 +4838,67 @@ theorem primCall_calldataload4_initialState_ofIR_arg0_ok_withStore .ok (state, [EvmYul.UInt256.div left right]) := by cases fuel <;> simp [EvmYul.Yul.primCall] <;> rfl -@[simp] theorem primCall_mod_ok - (fuel : Nat) +theorem step_div_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.DIV none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_div_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.DIV none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_div_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.DIV none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem primCall_div_nil_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.DIV [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel with + | zero => + simp [EvmYul.Yul.primCall, step_div_nil_invalid] + | succ fuel' => + simp [EvmYul.Yul.primCall, step_div_nil_invalid] + +theorem primCall_div_singleton_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.DIV [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel with + | zero => + simp [EvmYul.Yul.primCall, step_div_singleton_invalid] + | succ fuel' => + simp [EvmYul.Yul.primCall, step_div_singleton_invalid] + +theorem primCall_div_overarity_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.DIV + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel with + | zero => + simp [EvmYul.Yul.primCall, step_div_overarity_invalid] + | succ fuel' => + simp [EvmYul.Yul.primCall, step_div_overarity_invalid] + +@[simp] theorem primCall_mod_ok + (fuel : Nat) (state : EvmYul.Yul.State) (left right : EvmYul.UInt256) : EvmYul.Yul.primCall (fuel + 1) state @@ -2036,6 +4906,53 @@ theorem primCall_calldataload4_initialState_ofIR_arg0_ok_withStore .ok (state, [EvmYul.UInt256.mod left right]) := by cases fuel <;> simp [EvmYul.Yul.primCall] <;> rfl +theorem step_mod_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MOD none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mod_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MOD none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mod_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MOD none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem primCall_mod_nil_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.MOD [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_mod_nil_invalid] + +theorem primCall_mod_singleton_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.MOD [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_mod_singleton_invalid] + +theorem primCall_mod_overarity_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.MOD + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_mod_overarity_invalid] + @[simp] theorem primCall_sdiv_ok (fuel : Nat) (state : EvmYul.Yul.State) @@ -2151,6 +5068,53 @@ theorem primCall_calldataload0_then_shr224_initialState_selector_ok .ok (state, [EvmYul.UInt256.eq left right]) := by cases fuel <;> simp [EvmYul.Yul.primCall] +theorem step_eq_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.EQ none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_eq_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.EQ none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_eq_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.EQ none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem primCall_eq_nil_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.EQ [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_eq_nil_invalid] + +theorem primCall_eq_singleton_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.EQ [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_eq_singleton_invalid] + +theorem primCall_eq_overarity_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.EQ + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_eq_overarity_invalid] + @[simp] theorem primCall_iszero_ok (fuel : Nat) (state : EvmYul.Yul.State) @@ -2160,6 +5124,38 @@ theorem primCall_calldataload0_then_shr224_initialState_selector_ok .ok (state, [EvmYul.UInt256.isZero value]) := by cases fuel <;> simp [EvmYul.Yul.primCall] +theorem step_iszero_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.ISZERO none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_iszero_overarity_invalid + (state : EvmYul.Yul.State) + (value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.ISZERO none) state + (value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem primCall_iszero_nil_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.ISZERO [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_iszero_nil_invalid] + +theorem primCall_iszero_overarity_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.ISZERO + (value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_iszero_overarity_invalid] + @[simp] theorem primCall_lt_ok (fuel : Nat) (state : EvmYul.Yul.State) @@ -2169,6 +5165,53 @@ theorem primCall_calldataload0_then_shr224_initialState_selector_ok .ok (state, [EvmYul.UInt256.lt left right]) := by cases fuel <;> simp [EvmYul.Yul.primCall] +theorem step_lt_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.LT none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_lt_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.LT none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_lt_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.LT none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem primCall_lt_nil_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.LT [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_lt_nil_invalid] + +theorem primCall_lt_singleton_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.LT [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_lt_singleton_invalid] + +theorem primCall_lt_overarity_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.LT + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_lt_overarity_invalid] + @[simp] theorem primCall_gt_ok (fuel : Nat) (state : EvmYul.Yul.State) @@ -2178,6 +5221,53 @@ theorem primCall_calldataload0_then_shr224_initialState_selector_ok .ok (state, [EvmYul.UInt256.gt left right]) := by cases fuel <;> simp [EvmYul.Yul.primCall] <;> rfl +theorem step_gt_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.GT none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_gt_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.GT none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_gt_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.GT none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem primCall_gt_nil_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.GT [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_gt_nil_invalid] + +theorem primCall_gt_singleton_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.GT [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_gt_singleton_invalid] + +theorem primCall_gt_overarity_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.GT + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_gt_overarity_invalid] + @[simp] theorem primCall_slt_ok (fuel : Nat) (state : EvmYul.Yul.State) @@ -2279,6 +5369,73 @@ theorem primCall_calldataload0_then_shr224_initialState_selector_ok .ok (state, [state.executionEnv.getBlobGasprice]) := by cases fuel <;> simp [EvmYul.Yul.primCall] +theorem primCall_calldatasize_any_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.CALLDATASIZE values = + .ok (state, [EvmYul.UInt256.ofNat state.executionEnv.calldata.size]) := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_calldatasize_any] + +theorem primCall_callvalue_any_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.CALLVALUE values = + .ok (state, [state.executionEnv.weiValue]) := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_callvalue_any] + +theorem primCall_address_any_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.ADDRESS values = + .ok (state, [EvmYul.UInt256.ofNat state.executionEnv.codeOwner.val]) := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_address_any] + +theorem primCall_caller_any_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.CALLER values = + .ok (state, [EvmYul.UInt256.ofNat state.executionEnv.source.val]) := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_caller_any] + +theorem primCall_timestamp_any_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.TIMESTAMP values = + .ok (state, [state.toState.timeStamp]) := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_timestamp_any] + +theorem primCall_number_any_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.NUMBER values = + .ok (state, [state.toState.number]) := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_number_any] + +theorem primCall_chainid_any_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.CHAINID values = + .ok (state, [state.toState.chainId]) := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_chainid_any] + +theorem primCall_blobbasefee_any_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (values : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.BLOBBASEFEE values = + .ok (state, [state.executionEnv.getBlobGasprice]) := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_blobbasefee_any] + @[simp] theorem primCall_gasprice_ok (fuel : Nat) (state : EvmYul.Yul.State) : @@ -2347,6 +5504,38 @@ theorem primCall_calldataload0_then_shr224_initialState_selector_ok .ok (state, [EvmYul.UInt256.lnot value]) := by cases fuel <;> simp [EvmYul.Yul.primCall] <;> rfl +theorem step_not_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.NOT none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_not_overarity_invalid + (state : EvmYul.Yul.State) + (value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.NOT none) state + (value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem primCall_not_nil_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.NOT [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_not_nil_invalid] + +theorem primCall_not_overarity_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) + (value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.NOT + (value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_not_overarity_invalid] + @[simp] theorem primCall_shl_ok (fuel : Nat) (state : EvmYul.Yul.State) @@ -2374,225 +5563,791 @@ theorem primCall_calldataload0_then_shr224_initialState_selector_ok .ok (state, [EvmYul.UInt256.sar shift value]) := by cases fuel <;> simp [EvmYul.Yul.primCall] <;> rfl -@[simp] theorem primCall_mstore_ok - (fuel : Nat) +theorem step_sdiv_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SDIV none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sdiv_singleton_invalid (state : EvmYul.Yul.State) - (offset value : EvmYul.UInt256) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.MSTORE [offset, value] = - .ok (state.setMachineState (state.toMachineState.mstore offset value), - []) := by - cases fuel <;> simp [EvmYul.Yul.primCall] + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SDIV none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_mstore8_ok - (fuel : Nat) +theorem step_sdiv_overarity_invalid (state : EvmYul.Yul.State) - (offset value : EvmYul.UInt256) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.MSTORE8 [offset, value] = - .ok (state.setMachineState (state.toMachineState.mstore8 offset value), - []) := by - cases fuel <;> simp [EvmYul.Yul.primCall] + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SDIV none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_sload_ok - (fuel : Nat) +theorem step_smod_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SMOD none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_smod_singleton_invalid (state : EvmYul.Yul.State) - (slot : EvmYul.UInt256) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.SLOAD [slot] = - let (state', value) := state.toState.sload slot - .ok (state.setSharedState { state.toSharedState with toState := state' }, - [value]) := by - cases fuel <;> simp [EvmYul.Yul.primCall] + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SMOD none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_mload_ok - (fuel : Nat) +theorem step_smod_overarity_invalid (state : EvmYul.Yul.State) - (offset : EvmYul.UInt256) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.MLOAD [offset] = - let (value, machineState') := state.toSharedState.toMachineState.mload offset - .ok (state.setMachineState machineState', [value]) := by - cases fuel <;> simp [EvmYul.Yul.primCall] + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SMOD none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_keccak256_ok - (fuel : Nat) +theorem step_exp_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.EXP none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_exp_singleton_invalid (state : EvmYul.Yul.State) - (offset size : EvmYul.UInt256) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.KECCAK256 [offset, size] = - let (value, machineState') := state.toMachineState.keccak256 offset size - .ok (state.setMachineState machineState', [value]) := by - cases fuel <;> simp [EvmYul.Yul.primCall] + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.EXP none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_log0_ok - (fuel : Nat) +theorem step_exp_overarity_invalid (state : EvmYul.Yul.State) - (offset size : EvmYul.UInt256) - (hPerm : state.executionEnv.perm = true) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.LOG0 [offset, size] = - .ok (state.setSharedState - (EvmYul.SharedState.logOp offset size #[] state.toSharedState), []) := by - cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.EXP none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_log1_ok - (fuel : Nat) +theorem step_signextend_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SIGNEXTEND none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_signextend_singleton_invalid (state : EvmYul.Yul.State) - (offset size topic0 : EvmYul.UInt256) - (hPerm : state.executionEnv.perm = true) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.LOG1 [offset, size, topic0] = - .ok (state.setSharedState - (EvmYul.SharedState.logOp offset size #[topic0] state.toSharedState), []) := by - cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + (byteIdx : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SIGNEXTEND none) state [byteIdx] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_log2_ok - (fuel : Nat) +theorem step_signextend_overarity_invalid (state : EvmYul.Yul.State) - (offset size topic0 topic1 : EvmYul.UInt256) - (hPerm : state.executionEnv.perm = true) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.LOG2 [offset, size, topic0, topic1] = - .ok (state.setSharedState - (EvmYul.SharedState.logOp offset size #[topic0, topic1] - state.toSharedState), []) := by - cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + (byteIdx value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SIGNEXTEND none) state + (byteIdx :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_log3_ok - (fuel : Nat) +theorem step_slt_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SLT none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_slt_singleton_invalid (state : EvmYul.Yul.State) - (offset size topic0 topic1 topic2 : EvmYul.UInt256) - (hPerm : state.executionEnv.perm = true) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.LOG3 [offset, size, topic0, topic1, topic2] = - .ok (state.setSharedState - (EvmYul.SharedState.logOp offset size #[topic0, topic1, topic2] - state.toSharedState), []) := by - cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SLT none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_log4_ok - (fuel : Nat) +theorem step_slt_overarity_invalid (state : EvmYul.Yul.State) - (offset size topic0 topic1 topic2 topic3 : EvmYul.UInt256) - (hPerm : state.executionEnv.perm = true) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.LOG4 [offset, size, topic0, topic1, topic2, topic3] = - .ok (state.setSharedState - (EvmYul.SharedState.logOp offset size #[topic0, topic1, topic2, topic3] - state.toSharedState), []) := by - cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SLT none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_sstore_ok - (fuel : Nat) +theorem step_sgt_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SGT none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sgt_singleton_invalid (state : EvmYul.Yul.State) - (slot value : EvmYul.UInt256) - (hPerm : state.executionEnv.perm = true) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.SSTORE [slot, value] = - .ok (state.setState (state.toState.sstore slot value), []) := by - cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SGT none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl -@[simp] theorem primCall_tload_ok +theorem step_sgt_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SGT none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_and_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.AND none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_and_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.AND none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_and_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.AND none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_or_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.OR none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_or_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.OR none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_or_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.OR none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_xor_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.XOR none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_xor_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.XOR none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_xor_overarity_invalid + (state : EvmYul.Yul.State) + (left right extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.XOR none) state + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_shl_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SHL none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_shl_singleton_invalid + (state : EvmYul.Yul.State) + (shift : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SHL none) state [shift] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_shl_overarity_invalid + (state : EvmYul.Yul.State) + (shift value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SHL none) state + (shift :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_shr_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SHR none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_shr_singleton_invalid + (state : EvmYul.Yul.State) + (shift : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SHR none) state [shift] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_shr_overarity_invalid + (state : EvmYul.Yul.State) + (shift value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SHR none) state + (shift :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_byte_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.BYTE none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_byte_singleton_invalid + (state : EvmYul.Yul.State) + (index : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.BYTE none) state [index] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_byte_overarity_invalid + (state : EvmYul.Yul.State) + (index value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.BYTE none) state + (index :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sar_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SAR none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sar_singleton_invalid + (state : EvmYul.Yul.State) + (shift : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SAR none) state [shift] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sar_overarity_invalid + (state : EvmYul.Yul.State) + (shift value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SAR none) state + (shift :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sload_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SLOAD none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_sload_overarity_invalid + (state : EvmYul.Yul.State) + (slot extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.SLOAD none) state + (slot :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_calldataload_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.CALLDATALOAD none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_calldataload_overarity_invalid + (state : EvmYul.Yul.State) + (offset extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.CALLDATALOAD none) state + (offset :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mload_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MLOAD none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mload_overarity_invalid + (state : EvmYul.Yul.State) + (offset extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MLOAD none) state + (offset :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_tload_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.TLOAD none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_tload_overarity_invalid + (state : EvmYul.Yul.State) + (slot extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.TLOAD none) state + (slot :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_keccak256_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.KECCAK256 none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_keccak256_singleton_invalid + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.KECCAK256 none) state [offset] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_keccak256_overarity_invalid + (state : EvmYul.Yul.State) + (offset size extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.KECCAK256 none) state + (offset :: size :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_addmod_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.ADDMOD none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_addmod_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.ADDMOD none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_addmod_pair_invalid + (state : EvmYul.Yul.State) + (left right : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.ADDMOD none) state [left, right] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_addmod_overarity_invalid + (state : EvmYul.Yul.State) + (left right modulus extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.ADDMOD none) state + (left :: right :: modulus :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mulmod_nil_invalid + (state : EvmYul.Yul.State) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MULMOD none) state [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mulmod_singleton_invalid + (state : EvmYul.Yul.State) + (left : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MULMOD none) state [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mulmod_pair_invalid + (state : EvmYul.Yul.State) + (left right : EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MULMOD none) state [left, right] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +theorem step_mulmod_overarity_invalid + (state : EvmYul.Yul.State) + (left right modulus extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + (EvmYul.step (τ := .Yul) EvmYul.Operation.MULMOD none) state + (left :: right :: modulus :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + rfl + +@[simp] theorem primCall_mstore_ok (fuel : Nat) (state : EvmYul.Yul.State) - (slot : EvmYul.UInt256) : + (offset value : EvmYul.UInt256) : EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.TLOAD [slot] = - let (state', value) := state.toState.tload slot - .ok (state.setSharedState { state.toSharedState with toState := state' }, - [value]) := by + EvmYul.Operation.MSTORE [offset, value] = + .ok (state.setMachineState (state.toMachineState.mstore offset value), + []) := by cases fuel <;> simp [EvmYul.Yul.primCall] -@[simp] theorem primCall_tstore_ok +theorem primCall_mstore_nil_invalid + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.MSTORE [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_mstore_nil_invalid] + +theorem primCall_mstore_singleton_invalid (fuel : Nat) (state : EvmYul.Yul.State) - (slot value : EvmYul.UInt256) - (hPerm : state.executionEnv.perm = true) : + (offset : EvmYul.UInt256) : EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.TSTORE [slot, value] = - .ok (state.setState (state.toState.tstore slot value), []) := by - cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + EvmYul.Operation.MSTORE [offset] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_mstore_singleton_invalid] -@[simp] theorem primCall_msize_ok +theorem primCall_mstore_overarity_invalid (fuel : Nat) - (state : EvmYul.Yul.State) : - EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.MSIZE [] = - .ok (state, [state.toMachineState.msize]) := by - cases fuel <;> simp [EvmYul.Yul.primCall] + (state : EvmYul.Yul.State) + (offset value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.MSTORE (offset :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_mstore_overarity_invalid] -@[simp] theorem primCall_gas_ok +@[simp] theorem primCall_mstore8_ok (fuel : Nat) - (state : EvmYul.Yul.State) : - EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.GAS [] = - .ok (state, [state.toMachineState.gas]) := by + (state : EvmYul.Yul.State) + (offset value : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.MSTORE8 [offset, value] = + .ok (state.setMachineState (state.toMachineState.mstore8 offset value), + []) := by cases fuel <;> simp [EvmYul.Yul.primCall] -@[simp] theorem primCall_returndatasize_ok +theorem primCall_mstore8_nil_invalid (fuel : Nat) (state : EvmYul.Yul.State) : - EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.RETURNDATASIZE [] = - .ok (state, [state.toMachineState.returndatasize]) := by - cases fuel <;> simp [EvmYul.Yul.primCall] + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.MSTORE8 [] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_mstore8_nil_invalid] -@[simp] theorem primCall_calldatacopy_ok +theorem primCall_mstore8_singleton_invalid (fuel : Nat) (state : EvmYul.Yul.State) - (mstart datastart size : EvmYul.UInt256) : + (offset : EvmYul.UInt256) : EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.CALLDATACOPY [mstart, datastart, size] = - .ok (state.setSharedState - (state.toSharedState.calldatacopy mstart datastart size), []) := by - cases fuel <;> simp [EvmYul.Yul.primCall] + EvmYul.Operation.MSTORE8 [offset] = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_mstore8_singleton_invalid] -@[simp] theorem primCall_returndatacopy_ok +theorem primCall_mstore8_overarity_invalid (fuel : Nat) (state : EvmYul.Yul.State) - (mstart rstart size : EvmYul.UInt256) : + (offset value extra : EvmYul.UInt256) + (rest : List EvmYul.UInt256) : EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.RETURNDATACOPY [mstart, rstart, size] = - .ok (state.setMachineState - (state.toSharedState.toMachineState.returndatacopy mstart rstart size), - []) := by - cases fuel <;> simp [EvmYul.Yul.primCall] + EvmYul.Operation.MSTORE8 (offset :: value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments := by + cases fuel <;> simp [EvmYul.Yul.primCall, step_mstore8_overarity_invalid] -@[simp] theorem primCall_pop_ok +@[simp] theorem primCall_sload_ok (fuel : Nat) (state : EvmYul.Yul.State) - (value : EvmYul.UInt256) : - EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.POP [value] = - .ok (state, []) := by + (slot : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.SLOAD [slot] = + let (state', value) := state.toState.sload slot + .ok (state.setSharedState { state.toSharedState with toState := state' }, + [value]) := by cases fuel <;> simp [EvmYul.Yul.primCall] -@[simp] theorem primCall_stop_ok +@[simp] theorem primCall_mload_ok (fuel : Nat) - (state : EvmYul.Yul.State) : - EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.STOP [] = - .error (EvmYul.Yul.Exception.YulHalt state ⟨0⟩) := by + (state : EvmYul.Yul.State) + (offset : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.MLOAD [offset] = + let (value, machineState') := state.toSharedState.toMachineState.mload offset + .ok (state.setMachineState machineState', [value]) := by cases fuel <;> simp [EvmYul.Yul.primCall] -@[simp] theorem primCall_return_ok +@[simp] theorem primCall_keccak256_ok (fuel : Nat) (state : EvmYul.Yul.State) (offset size : EvmYul.UInt256) : EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.RETURN [offset, size] = - match EvmYul.Yul.binaryMachineStateOp EvmYul.MachineState.evmReturn - state [offset, size] with - | .error e => .error e - | .ok (s, value) => - .error (EvmYul.Yul.Exception.YulHalt s (value.getD ⟨1⟩)) := by + EvmYul.Operation.KECCAK256 [offset, size] = + let (value, machineState') := state.toMachineState.keccak256 offset size + .ok (state.setMachineState machineState', [value]) := by cases fuel <;> simp [EvmYul.Yul.primCall] - all_goals - cases EvmYul.Yul.binaryMachineStateOp EvmYul.MachineState.evmReturn - state [offset, size] <;> rfl -@[simp] theorem primCall_revert_ok +set_option linter.unusedSimpArgs false in +theorem nativeMappingSlotFunctionDefinition_exec_revivable (fuel : Nat) - (state : EvmYul.Yul.State) - (offset size : EvmYul.UInt256) : - EvmYul.Yul.primCall (fuel + 1) state - EvmYul.Operation.REVERT [offset, size] = + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (calleeState : EvmYul.Yul.State) + (hExec : + EvmYul.Yul.exec fuel (.Block nativeMappingSlotFunctionDefinition.body) + codeOverride (EvmYul.Yul.State.Ok shared store) = .ok calleeState) : + ∃ shared' store', + calleeState.reviveJump = EvmYul.Yul.State.Ok shared' store' := by + rw [nativeMappingSlotFunctionDefinition_body] at hExec + unfold nativeMappingSlotFunctionBody at hExec + cases fuel with + | zero => + simp [EvmYul.Yul.exec] at hExec + | succ f1 => + cases f1 with + | zero => + simp [EvmYul.Yul.exec] at hExec + | succ f2 => + cases f2 with + | zero => + simp [EvmYul.Yul.exec, EvmYul.Yul.execPrimCall, + EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, EvmYul.Yul.eval, + EvmYul.Yul.reverse'] at hExec + | succ f3 => + cases f3 with + | zero => + simp [EvmYul.Yul.exec, EvmYul.Yul.execPrimCall, + EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, EvmYul.Yul.eval, + EvmYul.Yul.reverse'] at hExec + | succ f4 => + cases f4 with + | zero => + simp [EvmYul.Yul.exec, EvmYul.Yul.execPrimCall, + EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, + EvmYul.Yul.eval, EvmYul.Yul.cons', + EvmYul.Yul.reverse'] at hExec + | succ f5 => + cases f5 with + | zero => + simp [EvmYul.Yul.exec, EvmYul.Yul.execPrimCall, + EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, + EvmYul.Yul.eval, EvmYul.Yul.cons', + EvmYul.Yul.reverse'] at hExec + | succ f6 => + cases f6 with + | zero => + simp [EvmYul.Yul.exec, EvmYul.Yul.execPrimCall, + EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, + EvmYul.Yul.eval, EvmYul.Yul.cons', + EvmYul.Yul.reverse'] at hExec + | succ f7 => + cases f7 with + | zero => + simp [EvmYul.Yul.exec, EvmYul.Yul.execPrimCall, + EvmYul.Yul.evalArgs, EvmYul.Yul.evalTail, + EvmYul.Yul.eval, EvmYul.Yul.cons', + EvmYul.Yul.reverse', EvmYul.Yul.multifill'] + at hExec + | succ f8 => + cases f8 with + | zero => + simp [EvmYul.Yul.exec, + EvmYul.Yul.execPrimCall, + EvmYul.Yul.evalArgs, + EvmYul.Yul.evalTail, EvmYul.Yul.eval, + EvmYul.Yul.cons', EvmYul.Yul.reverse', + EvmYul.Yul.multifill'] at hExec + | succ f9 => + simp [EvmYul.Yul.exec, + EvmYul.Yul.execPrimCall, + EvmYul.Yul.evalArgs, + EvmYul.Yul.evalTail, EvmYul.Yul.eval, + EvmYul.Yul.cons', EvmYul.Yul.reverse', + EvmYul.Yul.multifill', + EvmYul.Yul.State.multifill, + EvmYul.Yul.State.setMachineState, + EvmYul.Yul.State.lookup!, + EvmYul.Yul.State.insert, + EvmYul.Yul.State.reviveJump] at hExec ⊢ + subst calleeState + simp [EvmYul.Yul.State.reviveJump] + +@[simp] theorem primCall_log0_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (offset size : EvmYul.UInt256) + (hPerm : state.executionEnv.perm = true) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.LOG0 [offset, size] = + .ok (state.setSharedState + (EvmYul.SharedState.logOp offset size #[] state.toSharedState), []) := by + cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + +@[simp] theorem primCall_log1_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (offset size topic0 : EvmYul.UInt256) + (hPerm : state.executionEnv.perm = true) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.LOG1 [offset, size, topic0] = + .ok (state.setSharedState + (EvmYul.SharedState.logOp offset size #[topic0] state.toSharedState), []) := by + cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + +@[simp] theorem primCall_log2_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (offset size topic0 topic1 : EvmYul.UInt256) + (hPerm : state.executionEnv.perm = true) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.LOG2 [offset, size, topic0, topic1] = + .ok (state.setSharedState + (EvmYul.SharedState.logOp offset size #[topic0, topic1] + state.toSharedState), []) := by + cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + +@[simp] theorem primCall_log3_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (offset size topic0 topic1 topic2 : EvmYul.UInt256) + (hPerm : state.executionEnv.perm = true) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.LOG3 [offset, size, topic0, topic1, topic2] = + .ok (state.setSharedState + (EvmYul.SharedState.logOp offset size #[topic0, topic1, topic2] + state.toSharedState), []) := by + cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + +@[simp] theorem primCall_log4_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (offset size topic0 topic1 topic2 topic3 : EvmYul.UInt256) + (hPerm : state.executionEnv.perm = true) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.LOG4 [offset, size, topic0, topic1, topic2, topic3] = + .ok (state.setSharedState + (EvmYul.SharedState.logOp offset size #[topic0, topic1, topic2, topic3] + state.toSharedState), []) := by + cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + +@[simp] theorem primCall_sstore_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (slot value : EvmYul.UInt256) + (hPerm : state.executionEnv.perm = true) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.SSTORE [slot, value] = + .ok (state.setState (state.toState.sstore slot value), []) := by + cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + +@[simp] theorem primCall_tload_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (slot : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.TLOAD [slot] = + let (state', value) := state.toState.tload slot + .ok (state.setSharedState { state.toSharedState with toState := state' }, + [value]) := by + cases fuel <;> simp [EvmYul.Yul.primCall] + +@[simp] theorem primCall_tstore_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (slot value : EvmYul.UInt256) + (hPerm : state.executionEnv.perm = true) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.TSTORE [slot, value] = + .ok (state.setState (state.toState.tstore slot value), []) := by + cases fuel <;> simp [EvmYul.Yul.primCall, hPerm] + +@[simp] theorem primCall_msize_ok + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.MSIZE [] = + .ok (state, [state.toMachineState.msize]) := by + cases fuel <;> simp [EvmYul.Yul.primCall] + +@[simp] theorem primCall_gas_ok + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.GAS [] = + .ok (state, [state.toMachineState.gas]) := by + cases fuel <;> simp [EvmYul.Yul.primCall] + +@[simp] theorem primCall_returndatasize_ok + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.RETURNDATASIZE [] = + .ok (state, [state.toMachineState.returndatasize]) := by + cases fuel <;> simp [EvmYul.Yul.primCall] + +@[simp] theorem primCall_calldatacopy_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (mstart datastart size : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.CALLDATACOPY [mstart, datastart, size] = + .ok (state.setSharedState + (state.toSharedState.calldatacopy mstart datastart size), []) := by + cases fuel <;> simp [EvmYul.Yul.primCall] + +@[simp] theorem primCall_returndatacopy_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (mstart rstart size : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.RETURNDATACOPY [mstart, rstart, size] = + .ok (state.setMachineState + (state.toSharedState.toMachineState.returndatacopy mstart rstart size), + []) := by + cases fuel <;> simp [EvmYul.Yul.primCall] + +@[simp] theorem primCall_pop_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (value : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.POP [value] = + .ok (state, []) := by + cases fuel <;> simp [EvmYul.Yul.primCall] + +@[simp] theorem primCall_stop_ok + (fuel : Nat) + (state : EvmYul.Yul.State) : + EvmYul.Yul.primCall (fuel + 1) state EvmYul.Operation.STOP [] = + .error (EvmYul.Yul.Exception.YulHalt state ⟨0⟩) := by + cases fuel <;> simp [EvmYul.Yul.primCall] + +@[simp] theorem primCall_return_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (offset size : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.RETURN [offset, size] = + match EvmYul.Yul.binaryMachineStateOp EvmYul.MachineState.evmReturn + state [offset, size] with + | .error e => .error e + | .ok (s, value) => + .error (EvmYul.Yul.Exception.YulHalt s (value.getD ⟨1⟩)) := by + cases fuel <;> simp [EvmYul.Yul.primCall] + all_goals + cases EvmYul.Yul.binaryMachineStateOp EvmYul.MachineState.evmReturn + state [offset, size] <;> rfl + +@[simp] theorem primCall_revert_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (offset size : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) state + EvmYul.Operation.REVERT [offset, size] = match EvmYul.Yul.binaryMachineStateOp EvmYul.MachineState.evmRevert state [offset, size] with | .error e => .error e @@ -2602,11 +6357,6 @@ theorem primCall_calldataload0_then_shr224_initialState_selector_ok cases EvmYul.Yul.binaryMachineStateOp EvmYul.MachineState.evmRevert state [offset, size] <;> rfl -def nativeRevertZeroZeroStmt : EvmYul.Yul.Ast.Stmt := - .ExprStmtCall - (.Call (Sum.inl (EvmYul.Operation.REVERT : EvmYul.Operation .Yul)) - [.Lit (EvmYul.UInt256.ofNat 0), .Lit (EvmYul.UInt256.ofNat 0)]) - /-- The compiler's proof-side `revert(0, 0)` default lowers to the concrete native statement used by the selector-miss execution lemma. -/ theorem lowerStmtsNative_revert_zero_zero : @@ -2930,6 +6680,62 @@ theorem exec_lowerExprNative_mstore_lit_sload_lit_ok_fuel EvmYul.Yul.State.toSharedState, EvmYul.Yul.State.setSharedState, EvmYul.Yul.State.setMachineState, EvmYul.Yul.State.toMachineState] +/-- State-generic native `exec` of `mstore(memOffset, value)` when both + operands are generated literals. The Yul `VarStore` is unchanged and only + the machine memory is updated. -/ +theorem exec_lowerExprNative_mstore_lit_lit_ok_fuel + (fuel : Nat) + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (memOffset value : Nat) : + EvmYul.Yul.exec (fuel + 6) + (.ExprStmtCall (Backends.lowerExprNative + (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit memOffset, Yul.YulExpr.lit value]))) + codeOverride (.Ok shared store) = + .ok (.Ok { shared with + toMachineState := + shared.toMachineState.mstore + (EvmYul.UInt256.ofNat memOffset) + (EvmYul.UInt256.ofNat value) } + store) := by + simp [Backends.lowerExprNative, Backends.lookupRuntimePrimOp, + EvmYul.Yul.exec, EvmYul.Yul.eval, EvmYul.Yul.evalArgs, + EvmYul.Yul.evalTail, EvmYul.Yul.execPrimCall, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.State.multifill, EvmYul.Yul.State.setMachineState, + EvmYul.Yul.State.toMachineState] + +/-- State-generic native `exec` of `mstore(memOffset, calldataload(cdOffset))`. + The calldata read does not mutate shared state; only machine memory is + updated with the loaded word. -/ +theorem exec_lowerExprNative_mstore_lit_calldataload_lit_ok_fuel + (fuel : Nat) + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (memOffset cdOffset : Nat) : + EvmYul.Yul.exec (fuel + 8) + (.ExprStmtCall (Backends.lowerExprNative + (Yul.YulExpr.call "mstore" + [Yul.YulExpr.lit memOffset, + Yul.YulExpr.call "calldataload" [Yul.YulExpr.lit cdOffset]]))) + codeOverride (.Ok shared store) = + .ok (.Ok { shared with + toMachineState := + shared.toMachineState.mstore + (EvmYul.UInt256.ofNat memOffset) + (shared.calldataload (EvmYul.UInt256.ofNat cdOffset)) } + store) := by + simp [Backends.lowerExprNative, Backends.lookupRuntimePrimOp, + EvmYul.Yul.exec, EvmYul.Yul.eval, EvmYul.Yul.evalArgs, + EvmYul.Yul.evalTail, EvmYul.Yul.evalPrimCall, EvmYul.Yul.execPrimCall, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', + EvmYul.Yul.multifill', EvmYul.Yul.State.multifill, + EvmYul.Yul.State.toMachineState, + EvmYul.Yul.State.setMachineState] + /-- State-generic native `exec` of the `return(memOffset, memSize)` expression statement that the generated `retrieve()` body uses to surface the materialised slot-zero word as the call's return data. EVMYulLean models @@ -3520,6 +7326,106 @@ theorem exec_block_nil_ok .ok state := by simp [EvmYul.Yul.exec] +theorem exec_block_nil_ok_add_ten + (fuel suffixLen : Nat) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) : + EvmYul.Yul.exec (fuel + suffixLen + 10) (.Block []) codeOverride state = + .ok state := by + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_block_nil_ok (fuel + suffixLen + 9) codeOverride state) + +theorem exec_block_leave_ok_add_ten + (fuel suffixLen : Nat) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) : + EvmYul.Yul.exec (fuel + suffixLen + 10) (.Block [.Leave]) codeOverride + state = + .ok (state.setLeave) := by + have hFuel : + fuel + suffixLen + 10 = Nat.succ (Nat.succ (fuel + suffixLen + 8)) := by + omega + rw [hFuel] + simp [EvmYul.Yul.exec] + +/-- Executing the native lowering of a source `.block [.leave]` user body. + +`[.block [.leave]]` lowers to `[.Block [.Leave]]`; wrapped in the outer +dispatcher block this becomes `.Block [.Block [.Leave]]`. The inner `.Leave` +sets the leave flag on the underlying state, the inner block continues with +its empty tail, and the outer block likewise continues with an empty tail — +so the whole expression evaluates to `.ok state.setLeave`, identical to the +flat `.Block [.Leave]` case but consuming two extra fuel for the nested +block layer. -/ +theorem exec_block_block_leave_ok_add_ten + (fuel suffixLen : Nat) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) : + EvmYul.Yul.exec (fuel + suffixLen + 10) (.Block [.Block [.Leave]]) + codeOverride state = + .ok (state.setLeave) := by + have hFuel : + fuel + suffixLen + 10 = + Nat.succ (Nat.succ (Nat.succ (Nat.succ (fuel + suffixLen + 6)))) := by + omega + rw [hFuel] + simp [EvmYul.Yul.exec] + +/-- Executing the native lowering of a source `.block []` user body. + +`[.block []]` lowers to `[.Block []]`; wrapped in the outer dispatcher block +this becomes `.Block [.Block []]`. Both blocks fall through their empty +contents without setting the leave flag, so the whole expression evaluates to +`.ok state`. Mirrors `exec_block_block_leave_ok_add_ten` but with no inner +`.Leave` statement. -/ +theorem exec_block_block_nil_ok_add_ten + (fuel suffixLen : Nat) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) : + EvmYul.Yul.exec (fuel + suffixLen + 10) (.Block [.Block []]) + codeOverride state = + .ok state := by + have hFuel : + fuel + suffixLen + 10 = + Nat.succ (Nat.succ (Nat.succ (fuel + suffixLen + 7))) := by + omega + rw [hFuel] + simp [EvmYul.Yul.exec] + +theorem exec_block_stop_halt_add_ten + (fuel suffixLen : Nat) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) : + EvmYul.Yul.exec (fuel + suffixLen + 10) + (.Block [.ExprStmtCall (Backends.lowerExprNative (.call "stop" []))]) + codeOverride state = + .error (EvmYul.Yul.Exception.YulHalt state ⟨0⟩) := by + have hFuel : + fuel + suffixLen + 10 = + Nat.succ (Nat.succ (Nat.succ (fuel + suffixLen + 7))) := by + omega + rw [Backends.lowerExprNative_call_runtimePrimOp "stop" [] + EvmYul.Operation.STOP (by rfl)] + rw [hFuel] + simp [EvmYul.Yul.exec, EvmYul.Yul.execPrimCall, EvmYul.Yul.evalArgs, + EvmYul.Yul.reverse', EvmYul.Yul.multifill'] + +/-- Peel the no-op native statement emitted for a source Yul comment. + +Lowering `.comment` produces `.Block []`; this lemma removes that head block +from an enclosing native block while accounting for the two positive fuel +steps needed by the outer cons and the inner empty block. -/ +theorem exec_block_noop_block_head_eq + (fuel : Nat) + (rest : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) : + EvmYul.Yul.exec (Nat.succ (Nat.succ fuel)) + (.Block (.Block [] :: rest)) codeOverride state = + EvmYul.Yul.exec (Nat.succ fuel) (.Block rest) codeOverride state := + exec_block_cons_ok_eq (Nat.succ fuel) (.Block []) rest codeOverride state + state (exec_block_nil_ok fuel codeOverride state) + def nativeSwitchPrefixStmts (discrName matchedName : EvmYul.Identifier) : List EvmYul.Yul.Ast.Stmt := @@ -3552,7 +7458,7 @@ def nativeSwitchPrefixFinalState This packages the first two statements emitted by `lowerNativeSwitchBlock` for the generated dispatcher case and leaves the remaining case-chain proof with a -state whose native switch temporaries are aligned to the interpreter oracle. -/ +state whose native switch temporaries are aligned to the EVMYulLean fuel wrapper. -/ theorem exec_nativeSwitchPrefix_selector_initialState_ok (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) @@ -3765,6 +7671,49 @@ theorem exec_if_lowerExprNative_callvalue_skip_zero_fuel (.Ok shared store) (.Ok shared store) ?_ rw [eval_lowerExprNative_callvalue_ok_fuel, hWei] +/-- A native `UInt256` literal is zero whenever the source Nat is zero modulo +the EVM word modulus. -/ +theorem natToUInt256_eq_zero_of_mod_evm + (n : Nat) (hZero : n % evmModulus = 0) : + natToUInt256 n = (⟨0⟩ : EvmYul.Literal) := by + have hZero' : n % EvmYul.UInt256.size = 0 := by + simpa [evmModulus, EvmYul.UInt256.size] using hZero + change EvmYul.UInt256.ofNat n = EvmYul.UInt256.ofNat 0 + unfold EvmYul.UInt256.ofNat + simp [Id.run, Fin.ofNat, hZero'] + +/-- A native `UInt256` literal is nonzero whenever the source Nat is nonzero +modulo the EVM word modulus. -/ +theorem natToUInt256_ne_zero_of_mod_ne + (n : Nat) (hNonzero : n % evmModulus ≠ 0) : + natToUInt256 n ≠ (⟨0⟩ : EvmYul.Literal) := by + intro h + have hVal : n % EvmYul.UInt256.size = 0 := by + have hCong := congrArg (fun u : EvmYul.UInt256 => u.val.val) h + simpa [natToUInt256, EvmYul.UInt256.ofNat, Id.run, Fin.ofNat] using hCong + exact hNonzero (by simpa [evmModulus, EvmYul.UInt256.size] using hVal) + +/-- In the non-payable branch, `DispatchGuardsSafe` supplies the exact modular +zero fact needed to skip the lowered native `callvalue()` guard. -/ +theorem DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable + (fn : IRFunction) (tx : IRTransaction) + (hguards : DispatchGuardsSafe fn tx) + (hNonPayable : fn.payable = false) : + tx.msgValue % evmModulus = 0 := by + rcases hguards with ⟨hValueSafe, _⟩ + rcases hValueSafe with hPayable | hZero + · cases (by simp [hNonPayable] at hPayable : False) + · exact hZero + +/-- `DispatchGuardsSafe` records that the generated ABI calldata-size guard +threshold fits in a native EVM word. -/ +theorem DispatchGuardsSafe_calldata_threshold_lt + (fn : IRFunction) (tx : IRTransaction) + (hguards : DispatchGuardsSafe fn tx) : + 4 + fn.params.length * 32 < EvmYul.UInt256.size := by + exact by + simpa [evmModulus, EvmYul.UInt256.size] using hguards.2 + /-- General-`k` form of `uint256_lt_ofNat_4_eq_zero_of_ge`: when `k ≤ n` and both fit in `UInt256`, the EVMYulLean primitive `LT(ofNat n, ofNat k)` evaluates to the canonical zero word. Used to discharge the @@ -3790,6 +7739,30 @@ private theorem uint256_lt_ofNat_eq_zero_of_ge omega simp [EvmYul.UInt256.lt, hNotLt] +/-- General-`k` positive form of the native `LT(ofNat n, ofNat k)` primitive: +when `n < k` and both values fit in `UInt256`, the EVMYulLean primitive +evaluates to the canonical one word. -/ +private theorem uint256_lt_ofNat_eq_one_of_lt + (n k : Nat) (hLt : n < k) + (hSize : n < EvmYul.UInt256.size) + (hKSize : k < EvmYul.UInt256.size) : + EvmYul.UInt256.lt (EvmYul.UInt256.ofNat n) (EvmYul.UInt256.ofNat k) = + EvmYul.UInt256.ofNat 1 := by + have hN : (EvmYul.UInt256.ofNat n).val.val = n := by + unfold EvmYul.UInt256.ofNat + simp [Id.run, Fin.ofNat, Nat.mod_eq_of_lt hSize] + have hK : (EvmYul.UInt256.ofNat k).val.val = k := by + unfold EvmYul.UInt256.ofNat + simp [Id.run, Fin.ofNat, Nat.mod_eq_of_lt hKSize] + have hWordLt : + (EvmYul.UInt256.ofNat n : EvmYul.UInt256) < + (EvmYul.UInt256.ofNat k : EvmYul.UInt256) := by + change (EvmYul.UInt256.ofNat n).val.val < + (EvmYul.UInt256.ofNat k).val.val + rw [hN, hK] + exact hLt + simp [EvmYul.UInt256.lt, hWordLt] + /-- Native `if` execution skips the lowered `if lt(calldatasize(), k) { … }` revert guard whenever the current calldata is at least `k` bytes — i.e., when the caller has supplied enough calldata for the function's selector @@ -3821,6 +7794,58 @@ theorem exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel uint256_lt_ofNat_eq_zero_of_ge _ _ hGe hSize hKSize] rfl +/-- Native `if` execution takes the lowered `if lt(calldatasize(), k) { … }` + revert guard whenever the current calldata is shorter than `k` bytes. -/ +theorem exec_if_lowerExprNative_lt_calldatasize_take_lt_revert_fuel + (fuel : Nat) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (k : Nat) + (hSize : shared.executionEnv.calldata.size < EvmYul.UInt256.size) + (hKSize : k < EvmYul.UInt256.size) + (hLt : shared.executionEnv.calldata.size < k) : + EvmYul.Yul.exec (fuel + 9) + (.If (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit k])) + [nativeRevertZeroZeroStmt]) + codeOverride (.Ok shared store) = + .error EvmYul.Yul.Exception.Revert := by + have hEval : + EvmYul.Yul.eval (fuel + 8) + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit k])) + codeOverride (.Ok shared store) = + .ok (.Ok shared store, EvmYul.UInt256.ofNat 1) := by + rw [eval_lowerExprNative_lt_calldatasize_ok_fuel, + uint256_lt_ofNat_eq_one_of_lt _ _ hLt hSize hKSize] + have hBody : + EvmYul.Yul.exec (fuel + 8) (.Block [nativeRevertZeroZeroStmt]) + codeOverride (.Ok shared store) = + .error EvmYul.Yul.Exception.Revert := by + have hFuel : fuel + 8 = Nat.succ (fuel + 7) := by omega + rw [hFuel] + exact exec_block_cons_error (fuel + 7) nativeRevertZeroZeroStmt [] + codeOverride (.Ok shared store) EvmYul.Yul.Exception.Revert + (by + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_revert_zero_zero_error (fuel + 1) (.Ok shared store) + codeOverride)) + have hFuel : fuel + 9 = Nat.succ (fuel + 8) := by omega + rw [hFuel] + exact exec_if_eval_nonzero_error (fuel + 8) + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit k])) + [nativeRevertZeroZeroStmt] codeOverride (.Ok shared store) + (.Ok shared store) (EvmYul.UInt256.ofNat 1) + EvmYul.Yul.Exception.Revert hEval + (by decide) hBody + /-- Fuel-parametric form of `exec_if_lowerExprNative_iszero_ident_one_skip`. -/ theorem exec_if_lowerExprNative_iszero_ident_one_skip_fuel (fuel : Nat) @@ -4719,6 +8744,17 @@ theorem state_getElem_insert_of_ne | Checkpoint jump => simp [EvmYul.Yul.State.insert] +theorem state_getElem_insert_self_ok + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (name : EvmYul.Identifier) + (value : EvmYul.Literal) : + (((EvmYul.Yul.State.Ok shared store : EvmYul.Yul.State).insert + name value)[name]!) = value := by + simp [EvmYul.Yul.State.insert, EvmYul.Yul.State.lookup!, + EvmYul.Yul.State.store, GetElem?.getElem!, decidableGetElem?, + GetElem.getElem] + theorem state_getElem_multifill_of_not_mem (state : EvmYul.Yul.State) (name : EvmYul.Identifier) @@ -4837,6 +8873,28 @@ theorem NativePrimCallPreservesWord_calldatasize cases hExec exact hLookup +theorem NativePrimCallPreservesWord_calldatasize_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.CALLDATASIZE values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + exact NativePrimCallPreservesWord_calldatasize name expected + fuel state final rets hLookup hExec + | cons value rest => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [primCall_calldatasize_any_ok] at hExec + cases hExec + exact hLookup + theorem NativePrimCallPreservesWord_callvalue (name : EvmYul.Identifier) (expected : EvmYul.Literal) : @@ -4854,6 +8912,28 @@ theorem NativePrimCallPreservesWord_callvalue cases hExec exact hLookup +theorem NativePrimCallPreservesWord_callvalue_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.CALLVALUE values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + exact NativePrimCallPreservesWord_callvalue name expected + fuel state final rets hLookup hExec + | cons value rest => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [primCall_callvalue_any_ok] at hExec + cases hExec + exact hLookup + theorem NativePrimCallPreservesWord_address (name : EvmYul.Identifier) (expected : EvmYul.Literal) : @@ -4871,6 +8951,28 @@ theorem NativePrimCallPreservesWord_address cases hExec exact hLookup +theorem NativePrimCallPreservesWord_address_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.ADDRESS values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + exact NativePrimCallPreservesWord_address name expected + fuel state final rets hLookup hExec + | cons value rest => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [primCall_address_any_ok] at hExec + cases hExec + exact hLookup + theorem NativePrimCallPreservesWord_balance (name : EvmYul.Identifier) (expected account : EvmYul.Literal) : @@ -4929,6 +9031,28 @@ theorem NativePrimCallPreservesWord_caller cases hExec exact hLookup +theorem NativePrimCallPreservesWord_caller_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.CALLER values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + exact NativePrimCallPreservesWord_caller name expected + fuel state final rets hLookup hExec + | cons value rest => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [primCall_caller_any_ok] at hExec + cases hExec + exact hLookup + theorem NativePrimCallPreservesWord_timestamp (name : EvmYul.Identifier) (expected : EvmYul.Literal) : @@ -4946,6 +9070,28 @@ theorem NativePrimCallPreservesWord_timestamp cases hExec exact hLookup +theorem NativePrimCallPreservesWord_timestamp_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.TIMESTAMP values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + exact NativePrimCallPreservesWord_timestamp name expected + fuel state final rets hLookup hExec + | cons value rest => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [primCall_timestamp_any_ok] at hExec + cases hExec + exact hLookup + theorem NativePrimCallPreservesWord_number (name : EvmYul.Identifier) (expected : EvmYul.Literal) : @@ -4963,6 +9109,28 @@ theorem NativePrimCallPreservesWord_number cases hExec exact hLookup +theorem NativePrimCallPreservesWord_number_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.NUMBER values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + exact NativePrimCallPreservesWord_number name expected + fuel state final rets hLookup hExec + | cons value rest => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [primCall_number_any_ok] at hExec + cases hExec + exact hLookup + theorem NativePrimCallPreservesWord_chainid (name : EvmYul.Identifier) (expected : EvmYul.Literal) : @@ -4980,6 +9148,28 @@ theorem NativePrimCallPreservesWord_chainid cases hExec exact hLookup +theorem NativePrimCallPreservesWord_chainid_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.CHAINID values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + exact NativePrimCallPreservesWord_chainid name expected + fuel state final rets hLookup hExec + | cons value rest => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [primCall_chainid_any_ok] at hExec + cases hExec + exact hLookup + theorem NativePrimCallPreservesWord_blobbasefee (name : EvmYul.Identifier) (expected : EvmYul.Literal) : @@ -4997,6 +9187,28 @@ theorem NativePrimCallPreservesWord_blobbasefee cases hExec exact hLookup +theorem NativePrimCallPreservesWord_blobbasefee_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.BLOBBASEFEE values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + exact NativePrimCallPreservesWord_blobbasefee name expected + fuel state final rets hLookup hExec + | cons value rest => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [primCall_blobbasefee_any_ok] at hExec + cases hExec + exact hLookup + theorem NativePrimCallPreservesWord_gasprice (name : EvmYul.Identifier) (expected : EvmYul.Literal) : @@ -5086,6 +9298,51 @@ theorem NativePrimCallPreservesWord_unary_same_state cases hExec exact hLookup +theorem NativePrimCallPreservesWord_unary_same_state_values + (op : EvmYul.Operation .Yul) + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (hNil : + ∀ fuel state, + EvmYul.Yul.primCall (fuel + 1) state op [] = + Except.error EvmYul.Yul.Exception.InvalidArguments) + (hOverarity : + ∀ fuel state value extra rest, + EvmYul.Yul.primCall (fuel + 1) state op + (value :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments) + (hPrecise : + ∀ value, + ∀ fuel state final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state op [value] = + .ok (final, rets) → + final[name]! = expected) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state op values = .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [hNil fuel' state] at hExec + simp at hExec + | cons value rest => + cases rest with + | nil => + exact hPrecise value fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [hOverarity fuel' state value extra tail] at hExec + simp at hExec + theorem NativePrimCallPreservesWord_binary_same_state (op : EvmYul.Operation .Yul) (name : EvmYul.Identifier) @@ -5129,6 +9386,137 @@ theorem NativePrimCallPreservesWord_ternary_same_state cases hExec exact hLookup +theorem NativePrimCallPreservesWord_binary_same_state_values + (op : EvmYul.Operation .Yul) + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (hNil : + ∀ fuel state, + EvmYul.Yul.primCall (fuel + 1) state op [] = + Except.error EvmYul.Yul.Exception.InvalidArguments) + (hSingleton : + ∀ fuel state left, + EvmYul.Yul.primCall (fuel + 1) state op [left] = + Except.error EvmYul.Yul.Exception.InvalidArguments) + (hOverarity : + ∀ fuel state left right extra rest, + EvmYul.Yul.primCall (fuel + 1) state op + (left :: right :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments) + (hPrecise : + ∀ left right, + ∀ fuel state final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state op [left, right] = + .ok (final, rets) → + final[name]! = expected) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state op values = .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [hNil fuel' state] at hExec + simp at hExec + | cons left rest => + cases rest with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [hSingleton fuel' state left] at hExec + simp at hExec + | cons right rest => + cases rest with + | nil => + exact hPrecise left right fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [hOverarity fuel' state left right extra tail] at hExec + simp at hExec + +theorem NativePrimCallPreservesWord_ternary_same_state_values + (op : EvmYul.Operation .Yul) + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (hNil : + ∀ fuel state, + EvmYul.Yul.primCall (fuel + 1) state op [] = + Except.error EvmYul.Yul.Exception.InvalidArguments) + (hSingleton : + ∀ fuel state first, + EvmYul.Yul.primCall (fuel + 1) state op [first] = + Except.error EvmYul.Yul.Exception.InvalidArguments) + (hPair : + ∀ fuel state first second, + EvmYul.Yul.primCall (fuel + 1) state op [first, second] = + Except.error EvmYul.Yul.Exception.InvalidArguments) + (hOverarity : + ∀ fuel state first second third extra rest, + EvmYul.Yul.primCall (fuel + 1) state op + (first :: second :: third :: extra :: rest) = + Except.error EvmYul.Yul.Exception.InvalidArguments) + (hPrecise : + ∀ first second third, + ∀ fuel state final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state op [first, second, third] = + .ok (final, rets) → + final[name]! = expected) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state op values = .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [hNil fuel' state] at hExec + simp at hExec + | cons first rest => + cases rest with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [hSingleton fuel' state first] at hExec + simp at hExec + | cons second rest => + cases rest with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [hPair fuel' state first second] at hExec + simp at hExec + | cons third rest => + cases rest with + | nil => + exact hPrecise first second third fuel state final rets + hLookup hExec + | cons extra tail => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + rw [hOverarity fuel' state first second third extra tail] + at hExec + simp at hExec + theorem NativePrimCallPreservesWord_iszero (name : EvmYul.Identifier) (expected value : EvmYul.Literal) : @@ -5141,6 +9529,19 @@ theorem NativePrimCallPreservesWord_iszero name expected value (EvmYul.UInt256.isZero value) (by intro fuel state; exact primCall_iszero_ok fuel state value) +theorem NativePrimCallPreservesWord_iszero_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.ISZERO values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_unary_same_state_values EvmYul.Operation.ISZERO + name expected primCall_iszero_nil_invalid + primCall_iszero_overarity_invalid + (fun value => NativePrimCallPreservesWord_iszero name expected value) + theorem NativePrimCallPreservesWord_shr (name : EvmYul.Identifier) (expected shift value : EvmYul.Literal) : @@ -5153,6 +9554,24 @@ theorem NativePrimCallPreservesWord_shr name expected shift value (EvmYul.UInt256.shiftRight value shift) (by intro fuel state; exact primCall_shr_ok fuel state shift value) +theorem NativePrimCallPreservesWord_shr_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SHR values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.SHR + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_shr_nil_invalid]) + (by intro fuel state shift; cases fuel <;> + simp [EvmYul.Yul.primCall, step_shr_singleton_invalid]) + (by intro fuel state shift value extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_shr_overarity_invalid]) + (fun shift value => NativePrimCallPreservesWord_shr name expected shift value) + theorem NativePrimCallPreservesWord_add (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5165,6 +9584,48 @@ theorem NativePrimCallPreservesWord_add name expected left right (EvmYul.UInt256.add left right) (by intro fuel state; exact primCall_add_ok fuel state left right) +theorem NativePrimCallPreservesWord_add_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.ADD values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp only [EvmYul.Yul.primCall] at hExec + rw [step_add_nil_invalid] at hExec + simp at hExec + | cons left rest => + cases rest with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp only [EvmYul.Yul.primCall] at hExec + rw [step_add_singleton_invalid] at hExec + simp at hExec + | cons right rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_add name expected left right + fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp only [EvmYul.Yul.primCall] at hExec + rw [step_add_overarity_invalid] at hExec + simp at hExec + theorem NativePrimCallPreservesWord_sub (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5177,6 +9638,48 @@ theorem NativePrimCallPreservesWord_sub name expected left right (EvmYul.UInt256.sub left right) (by intro fuel state; exact primCall_sub_ok fuel state left right) +theorem NativePrimCallPreservesWord_sub_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SUB values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp only [EvmYul.Yul.primCall] at hExec + rw [step_sub_nil_invalid] at hExec + simp at hExec + | cons left rest => + cases rest with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp only [EvmYul.Yul.primCall] at hExec + rw [step_sub_singleton_invalid] at hExec + simp at hExec + | cons right rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_sub name expected left right + fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp only [EvmYul.Yul.primCall] at hExec + rw [step_sub_overarity_invalid] at hExec + simp at hExec + theorem NativePrimCallPreservesWord_mul (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5189,6 +9692,48 @@ theorem NativePrimCallPreservesWord_mul name expected left right (EvmYul.UInt256.mul left right) (by intro fuel state; exact primCall_mul_ok fuel state left right) +theorem NativePrimCallPreservesWord_mul_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.MUL values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp only [EvmYul.Yul.primCall] at hExec + rw [step_mul_nil_invalid] at hExec + simp at hExec + | cons left rest => + cases rest with + | nil => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp only [EvmYul.Yul.primCall] at hExec + rw [step_mul_singleton_invalid] at hExec + simp at hExec + | cons right rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_mul name expected left right + fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => + simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp only [EvmYul.Yul.primCall] at hExec + rw [step_mul_overarity_invalid] at hExec + simp at hExec + theorem NativePrimCallPreservesWord_div (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5201,6 +9746,19 @@ theorem NativePrimCallPreservesWord_div name expected left right (EvmYul.UInt256.div left right) (by intro fuel state; exact primCall_div_ok fuel state left right) +theorem NativePrimCallPreservesWord_div_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.DIV values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.DIV + name expected primCall_div_nil_invalid primCall_div_singleton_invalid + primCall_div_overarity_invalid + (fun left right => NativePrimCallPreservesWord_div name expected left right) + theorem NativePrimCallPreservesWord_mod (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5213,6 +9771,19 @@ theorem NativePrimCallPreservesWord_mod name expected left right (EvmYul.UInt256.mod left right) (by intro fuel state; exact primCall_mod_ok fuel state left right) +theorem NativePrimCallPreservesWord_mod_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.MOD values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.MOD + name expected primCall_mod_nil_invalid primCall_mod_singleton_invalid + primCall_mod_overarity_invalid + (fun left right => NativePrimCallPreservesWord_mod name expected left right) + theorem NativePrimCallPreservesWord_sdiv (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5225,6 +9796,24 @@ theorem NativePrimCallPreservesWord_sdiv name expected left right (EvmYul.UInt256.sdiv left right) (by intro fuel state; exact primCall_sdiv_ok fuel state left right) +theorem NativePrimCallPreservesWord_sdiv_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SDIV values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.SDIV + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sdiv_nil_invalid]) + (by intro fuel state left; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sdiv_singleton_invalid]) + (by intro fuel state left right extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sdiv_overarity_invalid]) + (fun left right => NativePrimCallPreservesWord_sdiv name expected left right) + theorem NativePrimCallPreservesWord_smod (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5237,6 +9826,24 @@ theorem NativePrimCallPreservesWord_smod name expected left right (EvmYul.UInt256.smod left right) (by intro fuel state; exact primCall_smod_ok fuel state left right) +theorem NativePrimCallPreservesWord_smod_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SMOD values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.SMOD + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_smod_nil_invalid]) + (by intro fuel state left; cases fuel <;> + simp [EvmYul.Yul.primCall, step_smod_singleton_invalid]) + (by intro fuel state left right extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_smod_overarity_invalid]) + (fun left right => NativePrimCallPreservesWord_smod name expected left right) + theorem NativePrimCallPreservesWord_addmod (name : EvmYul.Identifier) (expected left right modulus : EvmYul.Literal) : @@ -5250,6 +9857,27 @@ theorem NativePrimCallPreservesWord_addmod (EvmYul.UInt256.addMod left right modulus) (by intro fuel state; exact primCall_addmod_ok fuel state left right modulus) +theorem NativePrimCallPreservesWord_addmod_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.ADDMOD values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_ternary_same_state_values EvmYul.Operation.ADDMOD + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_addmod_nil_invalid]) + (by intro fuel state left; cases fuel <;> + simp [EvmYul.Yul.primCall, step_addmod_singleton_invalid]) + (by intro fuel state left right; cases fuel <;> + simp [EvmYul.Yul.primCall, step_addmod_pair_invalid]) + (by intro fuel state left right modulus extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_addmod_overarity_invalid]) + (fun left right modulus => + NativePrimCallPreservesWord_addmod name expected left right modulus) + theorem NativePrimCallPreservesWord_mulmod (name : EvmYul.Identifier) (expected left right modulus : EvmYul.Literal) : @@ -5263,6 +9891,27 @@ theorem NativePrimCallPreservesWord_mulmod (EvmYul.UInt256.mulMod left right modulus) (by intro fuel state; exact primCall_mulmod_ok fuel state left right modulus) +theorem NativePrimCallPreservesWord_mulmod_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.MULMOD values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_ternary_same_state_values EvmYul.Operation.MULMOD + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_mulmod_nil_invalid]) + (by intro fuel state left; cases fuel <;> + simp [EvmYul.Yul.primCall, step_mulmod_singleton_invalid]) + (by intro fuel state left right; cases fuel <;> + simp [EvmYul.Yul.primCall, step_mulmod_pair_invalid]) + (by intro fuel state left right modulus extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_mulmod_overarity_invalid]) + (fun left right modulus => + NativePrimCallPreservesWord_mulmod name expected left right modulus) + theorem NativePrimCallPreservesWord_exp (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5275,6 +9924,24 @@ theorem NativePrimCallPreservesWord_exp name expected left right (EvmYul.UInt256.exp left right) (by intro fuel state; exact primCall_exp_ok fuel state left right) +theorem NativePrimCallPreservesWord_exp_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.EXP values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.EXP + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_exp_nil_invalid]) + (by intro fuel state left; cases fuel <;> + simp [EvmYul.Yul.primCall, step_exp_singleton_invalid]) + (by intro fuel state left right extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_exp_overarity_invalid]) + (fun left right => NativePrimCallPreservesWord_exp name expected left right) + theorem NativePrimCallPreservesWord_signextend (name : EvmYul.Identifier) (expected byteIdx value : EvmYul.Literal) : @@ -5287,6 +9954,25 @@ theorem NativePrimCallPreservesWord_signextend name expected byteIdx value (EvmYul.UInt256.signextend byteIdx value) (by intro fuel state; exact primCall_signextend_ok fuel state byteIdx value) +theorem NativePrimCallPreservesWord_signextend_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SIGNEXTEND values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values + EvmYul.Operation.SIGNEXTEND name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_signextend_nil_invalid]) + (by intro fuel state byteIdx; cases fuel <;> + simp [EvmYul.Yul.primCall, step_signextend_singleton_invalid]) + (by intro fuel state byteIdx value extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_signextend_overarity_invalid]) + (fun byteIdx value => + NativePrimCallPreservesWord_signextend name expected byteIdx value) + theorem NativePrimCallPreservesWord_eq (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5299,10 +9985,23 @@ theorem NativePrimCallPreservesWord_eq name expected left right (EvmYul.UInt256.eq left right) (by intro fuel state; exact primCall_eq_ok fuel state left right) -theorem NativePrimCallPreservesWord_lt +theorem NativePrimCallPreservesWord_eq_values (name : EvmYul.Identifier) - (expected left right : EvmYul.Literal) : - ∀ fuel state final rets, + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.EQ values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.EQ + name expected primCall_eq_nil_invalid primCall_eq_singleton_invalid + primCall_eq_overarity_invalid + (fun left right => NativePrimCallPreservesWord_eq name expected left right) + +theorem NativePrimCallPreservesWord_lt + (name : EvmYul.Identifier) + (expected left right : EvmYul.Literal) : + ∀ fuel state final rets, state[name]! = expected → EvmYul.Yul.primCall fuel state EvmYul.Operation.LT [left, right] = .ok (final, rets) → @@ -5311,6 +10010,19 @@ theorem NativePrimCallPreservesWord_lt name expected left right (EvmYul.UInt256.lt left right) (by intro fuel state; exact primCall_lt_ok fuel state left right) +theorem NativePrimCallPreservesWord_lt_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.LT values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.LT + name expected primCall_lt_nil_invalid primCall_lt_singleton_invalid + primCall_lt_overarity_invalid + (fun left right => NativePrimCallPreservesWord_lt name expected left right) + theorem NativePrimCallPreservesWord_gt (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5323,6 +10035,19 @@ theorem NativePrimCallPreservesWord_gt name expected left right (EvmYul.UInt256.gt left right) (by intro fuel state; exact primCall_gt_ok fuel state left right) +theorem NativePrimCallPreservesWord_gt_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.GT values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.GT + name expected primCall_gt_nil_invalid primCall_gt_singleton_invalid + primCall_gt_overarity_invalid + (fun left right => NativePrimCallPreservesWord_gt name expected left right) + theorem NativePrimCallPreservesWord_slt (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5335,6 +10060,24 @@ theorem NativePrimCallPreservesWord_slt name expected left right (EvmYul.UInt256.slt left right) (by intro fuel state; exact primCall_slt_ok fuel state left right) +theorem NativePrimCallPreservesWord_slt_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SLT values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.SLT + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_slt_nil_invalid]) + (by intro fuel state left; cases fuel <;> + simp [EvmYul.Yul.primCall, step_slt_singleton_invalid]) + (by intro fuel state left right extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_slt_overarity_invalid]) + (fun left right => NativePrimCallPreservesWord_slt name expected left right) + theorem NativePrimCallPreservesWord_sgt (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5347,6 +10090,24 @@ theorem NativePrimCallPreservesWord_sgt name expected left right (EvmYul.UInt256.sgt left right) (by intro fuel state; exact primCall_sgt_ok fuel state left right) +theorem NativePrimCallPreservesWord_sgt_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SGT values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.SGT + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sgt_nil_invalid]) + (by intro fuel state left; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sgt_singleton_invalid]) + (by intro fuel state left right extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sgt_overarity_invalid]) + (fun left right => NativePrimCallPreservesWord_sgt name expected left right) + theorem NativePrimCallPreservesWord_and (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5359,6 +10120,24 @@ theorem NativePrimCallPreservesWord_and name expected left right (EvmYul.UInt256.land left right) (by intro fuel state; exact primCall_and_ok fuel state left right) +theorem NativePrimCallPreservesWord_and_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.AND values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.AND + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_and_nil_invalid]) + (by intro fuel state left; cases fuel <;> + simp [EvmYul.Yul.primCall, step_and_singleton_invalid]) + (by intro fuel state left right extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_and_overarity_invalid]) + (fun left right => NativePrimCallPreservesWord_and name expected left right) + theorem NativePrimCallPreservesWord_or (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5371,6 +10150,24 @@ theorem NativePrimCallPreservesWord_or name expected left right (EvmYul.UInt256.lor left right) (by intro fuel state; exact primCall_or_ok fuel state left right) +theorem NativePrimCallPreservesWord_or_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.OR values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.OR + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_or_nil_invalid]) + (by intro fuel state left; cases fuel <;> + simp [EvmYul.Yul.primCall, step_or_singleton_invalid]) + (by intro fuel state left right extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_or_overarity_invalid]) + (fun left right => NativePrimCallPreservesWord_or name expected left right) + theorem NativePrimCallPreservesWord_xor (name : EvmYul.Identifier) (expected left right : EvmYul.Literal) : @@ -5383,6 +10180,24 @@ theorem NativePrimCallPreservesWord_xor name expected left right (EvmYul.UInt256.xor left right) (by intro fuel state; exact primCall_xor_ok fuel state left right) +theorem NativePrimCallPreservesWord_xor_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.XOR values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.XOR + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_xor_nil_invalid]) + (by intro fuel state left; cases fuel <;> + simp [EvmYul.Yul.primCall, step_xor_singleton_invalid]) + (by intro fuel state left right extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_xor_overarity_invalid]) + (fun left right => NativePrimCallPreservesWord_xor name expected left right) + theorem NativePrimCallPreservesWord_not (name : EvmYul.Identifier) (expected value : EvmYul.Literal) : @@ -5395,6 +10210,18 @@ theorem NativePrimCallPreservesWord_not name expected value (EvmYul.UInt256.lnot value) (by intro fuel state; exact primCall_not_ok fuel state value) +theorem NativePrimCallPreservesWord_not_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.NOT values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_unary_same_state_values EvmYul.Operation.NOT + name expected primCall_not_nil_invalid primCall_not_overarity_invalid + (fun value => NativePrimCallPreservesWord_not name expected value) + theorem NativePrimCallPreservesWord_shl (name : EvmYul.Identifier) (expected shift value : EvmYul.Literal) : @@ -5407,6 +10234,24 @@ theorem NativePrimCallPreservesWord_shl name expected shift value (EvmYul.UInt256.shiftLeft value shift) (by intro fuel state; exact primCall_shl_ok fuel state shift value) +theorem NativePrimCallPreservesWord_shl_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SHL values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.SHL + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_shl_nil_invalid]) + (by intro fuel state shift; cases fuel <;> + simp [EvmYul.Yul.primCall, step_shl_singleton_invalid]) + (by intro fuel state shift value extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_shl_overarity_invalid]) + (fun shift value => NativePrimCallPreservesWord_shl name expected shift value) + theorem NativePrimCallPreservesWord_byte (name : EvmYul.Identifier) (expected index value : EvmYul.Literal) : @@ -5419,6 +10264,24 @@ theorem NativePrimCallPreservesWord_byte name expected index value (EvmYul.UInt256.byteAt index value) (by intro fuel state; exact primCall_byte_ok fuel state index value) +theorem NativePrimCallPreservesWord_byte_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.BYTE values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.BYTE + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_byte_nil_invalid]) + (by intro fuel state index; cases fuel <;> + simp [EvmYul.Yul.primCall, step_byte_singleton_invalid]) + (by intro fuel state index value extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_byte_overarity_invalid]) + (fun index value => NativePrimCallPreservesWord_byte name expected index value) + theorem NativePrimCallPreservesWord_sar (name : EvmYul.Identifier) (expected shift value : EvmYul.Literal) : @@ -5431,6 +10294,24 @@ theorem NativePrimCallPreservesWord_sar name expected shift value (EvmYul.UInt256.sar shift value) (by intro fuel state; exact primCall_sar_ok fuel state shift value) +theorem NativePrimCallPreservesWord_sar_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SAR values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.SAR + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sar_nil_invalid]) + (by intro fuel state shift; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sar_singleton_invalid]) + (by intro fuel state shift value extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sar_overarity_invalid]) + (fun shift value => NativePrimCallPreservesWord_sar name expected shift value) + theorem NativePrimCallPreservesWord_sload (name : EvmYul.Identifier) (expected slot : EvmYul.Literal) : @@ -5453,6 +10334,22 @@ theorem NativePrimCallPreservesWord_sload rw [state_getElem_setSharedState] exact hLookup +theorem NativePrimCallPreservesWord_sload_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SLOAD values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_unary_same_state_values EvmYul.Operation.SLOAD + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sload_nil_invalid]) + (by intro fuel state slot extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_sload_overarity_invalid]) + (fun slot => NativePrimCallPreservesWord_sload name expected slot) + theorem NativePrimCallPreservesWord_calldataload (name : EvmYul.Identifier) (expected offset : EvmYul.Literal) : @@ -5479,6 +10376,22 @@ theorem NativePrimCallPreservesWord_calldataload cases jump <;> simp [EvmYul.Yul.primCall] at hExec <;> cases hExec <;> exact hLookup +theorem NativePrimCallPreservesWord_calldataload_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.CALLDATALOAD values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_unary_same_state_values + EvmYul.Operation.CALLDATALOAD name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_calldataload_nil_invalid]) + (by intro fuel state offset extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_calldataload_overarity_invalid]) + (fun offset => NativePrimCallPreservesWord_calldataload name expected offset) + theorem NativePrimCallPreservesWord_mload (name : EvmYul.Identifier) (expected offset : EvmYul.Literal) : @@ -5501,6 +10414,22 @@ theorem NativePrimCallPreservesWord_mload rw [state_getElem_setMachineState] exact hLookup +theorem NativePrimCallPreservesWord_mload_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.MLOAD values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_unary_same_state_values EvmYul.Operation.MLOAD + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_mload_nil_invalid]) + (by intro fuel state offset extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_mload_overarity_invalid]) + (fun offset => NativePrimCallPreservesWord_mload name expected offset) + theorem NativePrimCallPreservesWord_mstore (name : EvmYul.Identifier) (expected offset value : EvmYul.Literal) : @@ -5519,6 +10448,20 @@ theorem NativePrimCallPreservesWord_mstore rw [state_getElem_setMachineState] exact hLookup +theorem NativePrimCallPreservesWord_mstore_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.MSTORE values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.MSTORE + name expected primCall_mstore_nil_invalid + primCall_mstore_singleton_invalid primCall_mstore_overarity_invalid + (fun offset value => + NativePrimCallPreservesWord_mstore name expected offset value) + theorem NativePrimCallPreservesWord_mstore8 (name : EvmYul.Identifier) (expected offset value : EvmYul.Literal) : @@ -5537,6 +10480,20 @@ theorem NativePrimCallPreservesWord_mstore8 rw [state_getElem_setMachineState] exact hLookup +theorem NativePrimCallPreservesWord_mstore8_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.MSTORE8 values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.MSTORE8 + name expected primCall_mstore8_nil_invalid + primCall_mstore8_singleton_invalid primCall_mstore8_overarity_invalid + (fun offset value => + NativePrimCallPreservesWord_mstore8 name expected offset value) + theorem NativePrimCallPreservesWord_tload (name : EvmYul.Identifier) (expected slot : EvmYul.Literal) : @@ -5559,6 +10516,22 @@ theorem NativePrimCallPreservesWord_tload rw [state_getElem_setSharedState] exact hLookup +theorem NativePrimCallPreservesWord_tload_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.TLOAD values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_unary_same_state_values EvmYul.Operation.TLOAD + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_tload_nil_invalid]) + (by intro fuel state slot extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_tload_overarity_invalid]) + (fun slot => NativePrimCallPreservesWord_tload name expected slot) + theorem NativePrimCallPreservesWord_tstore (name : EvmYul.Identifier) (expected slot value : EvmYul.Literal) : @@ -5585,6 +10558,77 @@ theorem NativePrimCallPreservesWord_tstore Except.ok (final, rets) at hExec cases hExec +theorem NativePrimCallPreservesWord_tstore_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.TSTORE values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm, step_tstore_nil_invalid] at hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + change + (Except.error EvmYul.Yul.Exception.StaticModeViolation : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Literal)) = + Except.ok (final, rets) at hExec + cases hExec + | cons slot rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm, + step_tstore_singleton_invalid] at hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + change + (Except.error EvmYul.Yul.Exception.StaticModeViolation : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Literal)) = + Except.ok (final, rets) at hExec + cases hExec + | cons value rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_tstore name expected slot value + fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm, + step_tstore_overarity_invalid] at hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + change + (Except.error EvmYul.Yul.Exception.StaticModeViolation : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Literal)) = + Except.ok (final, rets) at hExec + cases hExec + theorem NativePrimCallPreservesWord_sstore (name : EvmYul.Identifier) (expected slot value : EvmYul.Literal) : @@ -5611,6 +10655,77 @@ theorem NativePrimCallPreservesWord_sstore Except.ok (final, rets) at hExec cases hExec +theorem NativePrimCallPreservesWord_sstore_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.SSTORE values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm, step_sstore_nil_invalid] at hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + change + (Except.error EvmYul.Yul.Exception.StaticModeViolation : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Literal)) = + Except.ok (final, rets) at hExec + cases hExec + | cons slot rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm, + step_sstore_singleton_invalid] at hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + change + (Except.error EvmYul.Yul.Exception.StaticModeViolation : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Literal)) = + Except.ok (final, rets) at hExec + cases hExec + | cons value rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_sstore name expected slot value + fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm, + step_sstore_overarity_invalid] at hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + change + (Except.error EvmYul.Yul.Exception.StaticModeViolation : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Literal)) = + Except.ok (final, rets) at hExec + cases hExec + theorem NativePrimCallPreservesWord_stop (name : EvmYul.Identifier) (expected : EvmYul.Literal) : @@ -5673,6 +10788,72 @@ theorem NativePrimCallPreservesWord_revert rcases ret with ⟨revertState, value⟩ simp [hRevert] at hExec +theorem NativePrimCallPreservesWord_return_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.RETURN values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp [EvmYul.Yul.primCall, step_return_nil_invalid] at hExec + | cons offset rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp [EvmYul.Yul.primCall, step_return_singleton_invalid] at hExec + | cons size rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_return name expected offset size + fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp [EvmYul.Yul.primCall, step_return_overarity_invalid] at hExec + +theorem NativePrimCallPreservesWord_revert_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.REVERT values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp [EvmYul.Yul.primCall, step_revert_nil_invalid] at hExec + | cons offset rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp [EvmYul.Yul.primCall, step_revert_singleton_invalid] at hExec + | cons size rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_revert name expected offset size + fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + simp [EvmYul.Yul.primCall, step_revert_overarity_invalid] at hExec + theorem NativePrimCallPreservesWord_msize (name : EvmYul.Identifier) (expected : EvmYul.Literal) : @@ -5760,6 +10941,52 @@ theorem NativePrimCallPreservesWord_returndatacopy rw [state_getElem_setMachineState] exact hLookup +theorem NativePrimCallPreservesWord_calldatacopy_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.CALLDATACOPY values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_ternary_same_state_values + EvmYul.Operation.CALLDATACOPY name expected + (by intro fuel state; simp [EvmYul.Yul.primCall, + step_calldatacopy_nil_invalid]) + (by intro fuel state mstart; simp [EvmYul.Yul.primCall, + step_calldatacopy_singleton_invalid]) + (by intro fuel state mstart datastart; simp [EvmYul.Yul.primCall, + step_calldatacopy_pair_invalid]) + (by + intro fuel state mstart datastart size extra rest + simp [EvmYul.Yul.primCall, step_calldatacopy_overarity_invalid]) + (fun mstart datastart size => + NativePrimCallPreservesWord_calldatacopy name expected mstart datastart + size) + +theorem NativePrimCallPreservesWord_returndatacopy_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.RETURNDATACOPY values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_ternary_same_state_values + EvmYul.Operation.RETURNDATACOPY name expected + (by intro fuel state; simp [EvmYul.Yul.primCall, + step_returndatacopy_nil_invalid]) + (by intro fuel state mstart; simp [EvmYul.Yul.primCall, + step_returndatacopy_singleton_invalid]) + (by intro fuel state mstart rstart; simp [EvmYul.Yul.primCall, + step_returndatacopy_pair_invalid]) + (by + intro fuel state mstart rstart size extra rest + simp [EvmYul.Yul.primCall, step_returndatacopy_overarity_invalid]) + (fun mstart rstart size => + NativePrimCallPreservesWord_returndatacopy name expected mstart rstart + size) + theorem NativePrimCallPreservesWord_pop (name : EvmYul.Identifier) (expected value : EvmYul.Literal) : @@ -5799,6 +11026,25 @@ theorem NativePrimCallPreservesWord_keccak256 rw [state_getElem_setMachineState] exact hLookup +theorem NativePrimCallPreservesWord_keccak256_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.KECCAK256 values = + .ok (final, rets) → + final[name]! = expected := + NativePrimCallPreservesWord_binary_same_state_values EvmYul.Operation.KECCAK256 + name expected + (by intro fuel state; cases fuel <;> + simp [EvmYul.Yul.primCall, step_keccak256_nil_invalid]) + (by intro fuel state offset; cases fuel <;> + simp [EvmYul.Yul.primCall, step_keccak256_singleton_invalid]) + (by intro fuel state offset size extra rest; cases fuel <;> + simp [EvmYul.Yul.primCall, step_keccak256_overarity_invalid]) + (fun offset size => + NativePrimCallPreservesWord_keccak256 name expected offset size) + theorem NativePrimCallPreservesWord_log0 (name : EvmYul.Identifier) (expected offset size : EvmYul.Literal) : @@ -5924,6 +11170,548 @@ theorem NativePrimCallPreservesWord_log4 simp [EvmYul.Yul.primCall, hPermFalse] at hExec cases hExec +theorem NativePrimCallPreservesWord_noop_result + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + {state final : EvmYul.Yul.State} + {rets : List EvmYul.Literal} + (hLookup : state[name]! = expected) + (hExec : state = final ∧ rets = []) : + final[name]! = expected := by + rcases hExec with ⟨hFinal, _⟩ + subst final + exact hLookup + +theorem NativePrimCallPreservesWord_log0_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.LOG0 values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons offset rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons size rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_log0 name expected offset size + fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + +theorem NativePrimCallPreservesWord_log1_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.LOG1 values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons offset rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons size rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons topic0 rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_log1 name expected offset size + topic0 fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + +theorem NativePrimCallPreservesWord_log2_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.LOG2 values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons offset rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons size rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons topic0 rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons topic1 rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_log2 name expected + offset size topic0 topic1 fuel state final rets hLookup + hExec + | cons extra tail => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : + state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + +theorem NativePrimCallPreservesWord_log3_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.LOG3 values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons offset rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons size rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons topic0 rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons topic1 rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : + state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons topic2 rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_log3 name expected + offset size topic0 topic1 topic2 fuel state final + rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : + state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : + state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + +theorem NativePrimCallPreservesWord_log4_values + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state EvmYul.Operation.LOG4 values = + .ok (final, rets) → + final[name]! = expected := by + intro fuel state values final rets hLookup hExec + cases values with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons offset rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons size rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons topic0 rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons topic1 rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : + state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : + state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons topic2 rest => + cases rest with + | nil => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : + state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : + state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] at hExec + cases hExec + | cons topic3 rest => + cases rest with + | nil => + exact NativePrimCallPreservesWord_log4 name + expected offset size topic0 topic1 topic2 topic3 + fuel state final rets hLookup hExec + | cons extra tail => + cases fuel with + | zero => simp [EvmYul.Yul.primCall] at hExec + | succ fuel' => + by_cases hPerm : + state.executionEnv.perm = true + · simp [EvmYul.Yul.primCall, hPerm] at hExec + exact NativePrimCallPreservesWord_noop_result + name expected hLookup hExec + · have hPermFalse : + state.executionEnv.perm = false := by + cases hp : state.executionEnv.perm + · rfl + · exact False.elim (hPerm hp) + simp [EvmYul.Yul.primCall, hPermFalse] + at hExec + cases hExec + +theorem NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp + (name func : EvmYul.Identifier) + (expected : EvmYul.Literal) + (op : EvmYul.Operation .Yul) + (hAllowed : + Compiler.Proofs.YulGeneration.Backends.allowedExprCallName func) + (hOp : Backends.lookupRuntimePrimOp func = some op) : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state op values = .ok (final, rets) → + final[name]! = expected := by + unfold Backends.lookupRuntimePrimOp at hOp + split at hOp <;> cases hOp <;> + first + | exact NativePrimCallPreservesWord_add_values name expected + | exact NativePrimCallPreservesWord_sub_values name expected + | exact NativePrimCallPreservesWord_mul_values name expected + | exact NativePrimCallPreservesWord_div_values name expected + | exact NativePrimCallPreservesWord_sdiv_values name expected + | exact NativePrimCallPreservesWord_mod_values name expected + | exact NativePrimCallPreservesWord_smod_values name expected + | exact NativePrimCallPreservesWord_addmod_values name expected + | exact NativePrimCallPreservesWord_mulmod_values name expected + | exact NativePrimCallPreservesWord_exp_values name expected + | exact NativePrimCallPreservesWord_signextend_values name expected + | exact NativePrimCallPreservesWord_lt_values name expected + | exact NativePrimCallPreservesWord_gt_values name expected + | exact NativePrimCallPreservesWord_slt_values name expected + | exact NativePrimCallPreservesWord_sgt_values name expected + | exact NativePrimCallPreservesWord_eq_values name expected + | exact NativePrimCallPreservesWord_iszero_values name expected + | exact NativePrimCallPreservesWord_and_values name expected + | exact NativePrimCallPreservesWord_or_values name expected + | exact NativePrimCallPreservesWord_xor_values name expected + | exact NativePrimCallPreservesWord_not_values name expected + | exact NativePrimCallPreservesWord_byte_values name expected + | exact NativePrimCallPreservesWord_shl_values name expected + | exact NativePrimCallPreservesWord_shr_values name expected + | exact NativePrimCallPreservesWord_sar_values name expected + | exact NativePrimCallPreservesWord_keccak256_values name expected + | exact NativePrimCallPreservesWord_address_values name expected + | exact NativePrimCallPreservesWord_caller_values name expected + | exact NativePrimCallPreservesWord_callvalue_values name expected + | exact NativePrimCallPreservesWord_calldataload_values name expected + | exact NativePrimCallPreservesWord_calldatasize_values name expected + | exact NativePrimCallPreservesWord_timestamp_values name expected + | exact NativePrimCallPreservesWord_number_values name expected + | exact NativePrimCallPreservesWord_chainid_values name expected + | exact NativePrimCallPreservesWord_blobbasefee_values name expected + | exact NativePrimCallPreservesWord_mload_values name expected + | exact NativePrimCallPreservesWord_sload_values name expected + | exact NativePrimCallPreservesWord_tload_values name expected + | exfalso + simp [Compiler.Proofs.YulGeneration.Backends.allowedExprCallName, + Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins] at hAllowed + theorem NativeExprPreservesWord_var (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -6150,6 +11938,23 @@ theorem NativeExprPreservesWord_call_prim_of_evalArgs_primCall_preserves exact hPrim fuel' argState values.reverse primState (ret :: rest) hArgLookup hPrimCall +theorem NativeExprPreservesWord_call_prim_of_nativeEvalArgs_primCall_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (prim : EvmYul.Yul.Ast.PrimOp) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hPrim : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state prim values = .ok (final, rets) → + final[name]! = expected) : + NativeExprPreservesWord name expected + (.Call (Sum.inl prim) args) codeOverride := + NativeExprPreservesWord_call_prim_of_evalArgs_primCall_preserves + name expected prim args codeOverride hArgs hPrim + theorem NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves (name func : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -6221,6 +12026,20 @@ theorem NativeExprPreservesWord_call_user_of_evalArgs_call_preserves exact hCall callFuel argState values.reverse callState (ret :: rest) hArgLookup hUserCall +theorem NativeExprPreservesWord_call_user_of_nativeEvalArgs_call_preserves + (name : EvmYul.Identifier) (expected : EvmYul.Literal) + (functionName : EvmYul.Yul.Ast.YulFunctionName) (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hCall : + ∀ fuel state values final rets, state[name]! = expected → + EvmYul.Yul.call fuel values (some functionName) codeOverride state = + .ok (final, rets) → final[name]! = expected) : + NativeExprPreservesWord name expected (.Call (Sum.inr functionName) args) + codeOverride := + NativeExprPreservesWord_call_user_of_evalArgs_call_preserves + name expected functionName args codeOverride hArgs hCall + theorem NativeExprPreservesWord_lowerExprNative_call_userFunction_of_evalArgs_call_preserves (name func : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -6243,25 +12062,512 @@ theorem NativeExprPreservesWord_lowerExprNative_call_userFunction_of_evalArgs_ca name expected func (args.map Backends.lowerExprNative) codeOverride hArgs hCall -theorem state_getElem_overwrite?_left - (state next : EvmYul.Yul.State) - (name : EvmYul.Identifier) - (hOk : ∃ shared store, next = EvmYul.Yul.State.Ok shared store) : - (state.overwrite? next)[name]! = state[name]! := by - rcases hOk with ⟨shared, store, rfl⟩ - cases state <;> rfl - -theorem state_getElem_restoreCallFrame_of_ok - (state next : EvmYul.Yul.State) - (name : EvmYul.Identifier) - (hState : ∃ shared store, state = EvmYul.Yul.State.Ok shared store) - (hNext : ∃ shared store, next.reviveJump = EvmYul.Yul.State.Ok shared store) : - ((next.reviveJump.overwrite? state).setStore state)[name]! = state[name]! := by +theorem NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + (name func : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (op : EvmYul.Operation .Yul) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hOp : Backends.lookupRuntimePrimOp func = some op) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hPrim : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state op values = .ok (final, rets) → + final[name]! = expected) : + NativeExprPreservesWord name expected + (Backends.lowerExprNative (.call func args)) codeOverride := + NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves + name func expected args op codeOverride hOp hArgs hPrim + +theorem NativeExprPreservesWord_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves + (name func : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hOp : Backends.lookupRuntimePrimOp func = none) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hCall : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.call fuel values (some func) codeOverride state = + .ok (final, rets) → + final[name]! = expected) : + NativeExprPreservesWord name expected + (Backends.lowerExprNative (.call func args)) codeOverride := + NativeExprPreservesWord_lowerExprNative_call_userFunction_of_evalArgs_call_preserves + name func expected args codeOverride hOp hArgs hCall + +theorem state_getElem_overwrite?_left + (state next : EvmYul.Yul.State) + (name : EvmYul.Identifier) + (hOk : ∃ shared store, next = EvmYul.Yul.State.Ok shared store) : + (state.overwrite? next)[name]! = state[name]! := by + rcases hOk with ⟨shared, store, rfl⟩ + cases state <;> rfl + +theorem state_getElem_restoreCallFrame_of_ok + (state next : EvmYul.Yul.State) + (name : EvmYul.Identifier) + (hState : ∃ shared store, state = EvmYul.Yul.State.Ok shared store) + (hNext : ∃ shared store, next.reviveJump = EvmYul.Yul.State.Ok shared store) : + ((next.reviveJump.overwrite? state).setStore state)[name]! = state[name]! := by rcases hState with ⟨shared, store, rfl⟩ rcases hNext with ⟨shared', store', hNextOk⟩ simp [EvmYul.Yul.State.overwrite?] rw [hNextOk, state_getElem_setStore_ok] +theorem native_call_preserves_lookup_of_revivable_body + (name functionName : EvmYul.Identifier) + (expected : EvmYul.Literal) + (fuel : Nat) + (values : List EvmYul.Literal) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (final : EvmYul.Yul.State) + (rets : List EvmYul.Literal) + (hLookup : + ((EvmYul.Yul.State.Ok shared store) : EvmYul.Yul.State)[name]! = + expected) + (hRevivable : + ∀ (yulContract : EvmYul.Account .Yul) + (functionDef : EvmYul.Yul.Ast.FunctionDefinition) + (calleeState : EvmYul.Yul.State), + (codeOverride.getD yulContract.code).functions.lookup functionName = + some functionDef → + EvmYul.Yul.exec (fuel - 1) + (.Block functionDef.body) codeOverride + (EvmYul.Yul.State.mkOk + (EvmYul.Yul.State.initcall functionDef.params values + (EvmYul.Yul.State.Ok shared store))) = + .ok calleeState → + ∃ shared' store', + calleeState.reviveJump = EvmYul.Yul.State.Ok shared' store') + (hCall : + EvmYul.Yul.call fuel values (some functionName) codeOverride + (EvmYul.Yul.State.Ok shared store) = + .ok (final, rets)) : + final[name]! = expected := by + cases fuel with + | zero => + simp [EvmYul.Yul.call] at hCall + | succ fuel' => + simp only [EvmYul.Yul.call] at hCall + cases hCode : + (EvmYul.Yul.State.Ok shared store).sharedState.accountMap.find? + (EvmYul.Yul.State.Ok shared store).executionEnv.codeOwner with + | none => + simp [hCode] at hCall + | some yulContract => + simp [hCode] at hCall + cases hFunction : + (codeOverride.getD yulContract.code).functions.lookup + functionName with + | none => + simp [hFunction] at hCall + | some functionDef => + simp [hFunction] at hCall + cases hExec : + EvmYul.Yul.exec fuel' + (.Block functionDef.body) codeOverride + (EvmYul.Yul.State.mkOk + (EvmYul.Yul.State.initcall functionDef.params values + (EvmYul.Yul.State.Ok shared store))) with + | error err => + simp [hExec] at hCall + | ok calleeState => + simp [hExec] at hCall + rcases hCall with ⟨hFinal, _⟩ + subst final + exact + state_getElem_restoreCallFrame_of_ok + (EvmYul.Yul.State.Ok shared store) calleeState name + ⟨shared, store, rfl⟩ + (hRevivable yulContract functionDef calleeState + hFunction (by simpa using hExec)) ▸ hLookup + +theorem nativeMappingSlotFunctionDefinition_exec_revivable_of_ok_state + (fuel : Nat) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state calleeState : EvmYul.Yul.State) + (hState : ∃ shared store, state = EvmYul.Yul.State.Ok shared store) + (hExec : + EvmYul.Yul.exec fuel (.Block nativeMappingSlotFunctionDefinition.body) + codeOverride state = .ok calleeState) : + ∃ shared' store', + calleeState.reviveJump = EvmYul.Yul.State.Ok shared' store' := by + rcases hState with ⟨shared, store, rfl⟩ + exact + nativeMappingSlotFunctionDefinition_exec_revivable fuel codeOverride + shared store calleeState hExec + +theorem state_foldr_insert_ok_exists + (entries : List (EvmYul.Identifier × EvmYul.Literal)) + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) : + ∃ shared' store', + entries.foldr (fun entry state => + EvmYul.Yul.State.insert entry.1 entry.2 state) + (EvmYul.Yul.State.Ok shared store) = + EvmYul.Yul.State.Ok shared' store' := by + induction entries with + | nil => + exact ⟨shared, store, rfl⟩ + | cons entry entries ih => + rcases ih with ⟨shared', store', h⟩ + rw [List.foldr_cons, h] + exact ⟨shared', store'.insert entry.1 entry.2, rfl⟩ + +theorem state_mkOk_initcall_ok_exists + (params : List EvmYul.Identifier) + (values : List EvmYul.Literal) + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) : + ∃ shared' store', + EvmYul.Yul.State.mkOk + (EvmYul.Yul.State.initcall params values + (EvmYul.Yul.State.Ok shared store)) = + EvmYul.Yul.State.Ok shared' store' := by + simp [EvmYul.Yul.State.initcall, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.multifill] + let emptyStore : EvmYul.Yul.VarStore := Inhabited.default + rcases state_foldr_insert_ok_exists (List.zip params values) shared + emptyStore with + ⟨shared', store', hFill⟩ + exact ⟨shared', store', by rw [hFill]; rfl⟩ + +theorem native_mappingSlot_call_preserves_lookup + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (fuel : Nat) + (values : List EvmYul.Literal) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (final : EvmYul.Yul.State) + (rets : List EvmYul.Literal) + (hLookup : + ((EvmYul.Yul.State.Ok shared store) : EvmYul.Yul.State)[name]! = + expected) + (hCall : + EvmYul.Yul.call fuel values (some "mappingSlot") + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + (EvmYul.Yul.State.Ok shared store) = + .ok (final, rets)) : + final[name]! = expected := by + apply + native_call_preserves_lookup_of_revivable_body name "mappingSlot" + expected fuel values + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + shared store final rets hLookup + · intro yulContract functionDef calleeState hFunction hExec + simp only [Option.getD_some] at hFunction + rw [Finmap.lookup_insert] at hFunction + injection hFunction with hDef + subst functionDef + exact + nativeMappingSlotFunctionDefinition_exec_revivable_of_ok_state + (fuel - 1) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + (EvmYul.Yul.State.mkOk + (EvmYul.Yul.State.initcall nativeMappingSlotFunctionDefinition.params + values (EvmYul.Yul.State.Ok shared store))) + calleeState + (state_mkOk_initcall_ok_exists + nativeMappingSlotFunctionDefinition.params values shared store) + hExec + · exact hCall + +theorem native_mappingSlot_call_preserves_lookup_state + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (fuel : Nat) + (values : List EvmYul.Literal) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (state final : EvmYul.Yul.State) + (rets : List EvmYul.Literal) + (hLookup : state[name]! = expected) + (hCall : + EvmYul.Yul.call fuel values (some "mappingSlot") + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (final, rets)) : + final[name]! = expected := by + cases state with + | Ok shared store => + exact + native_mappingSlot_call_preserves_lookup name expected fuel values + dispatcher shared store final rets hLookup hCall + | OutOfFuel => + cases fuel with + | zero => + simp [EvmYul.Yul.call] at hCall + | succ fuel' => + simp only [EvmYul.Yul.call] at hCall + cases hCode : + EvmYul.Yul.State.OutOfFuel.sharedState.accountMap.find? + EvmYul.Yul.State.OutOfFuel.executionEnv.codeOwner with + | none => + simp [hCode] at hCall + | some yulContract => + simp [hCode] at hCall + cases hExec : + EvmYul.Yul.exec fuel' + (.Block nativeMappingSlotFunctionDefinition.body) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + (EvmYul.Yul.State.mkOk + (EvmYul.Yul.State.initcall + nativeMappingSlotFunctionDefinition.params values + EvmYul.Yul.State.OutOfFuel)) with + | error err => + simp [hExec] at hCall + | ok calleeState => + simp [hExec, EvmYul.Yul.State.overwrite?, + EvmYul.Yul.State.setStore] at hCall + rcases hCall with ⟨rfl, _⟩ + exact hLookup + | Checkpoint jump => + cases fuel with + | zero => + simp [EvmYul.Yul.call] at hCall + | succ fuel' => + simp only [EvmYul.Yul.call] at hCall + cases hCode : + (EvmYul.Yul.State.Checkpoint jump).sharedState.accountMap.find? + (EvmYul.Yul.State.Checkpoint jump).executionEnv.codeOwner with + | none => + simp [hCode] at hCall + | some yulContract => + simp [hCode] at hCall + cases hExec : + EvmYul.Yul.exec fuel' + (.Block nativeMappingSlotFunctionDefinition.body) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + (EvmYul.Yul.State.mkOk + (EvmYul.Yul.State.initcall + nativeMappingSlotFunctionDefinition.params values + (EvmYul.Yul.State.Checkpoint jump))) with + | error err => + simp [hExec] at hCall + | ok calleeState => + simp [hExec, EvmYul.Yul.State.overwrite?, + EvmYul.Yul.State.setStore] at hCall + rcases hCall with ⟨rfl, _⟩ + exact hLookup + +theorem NativeExprPreservesWord_lowerExprNative_mappingSlot_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) })) : + NativeExprPreservesWord name expected + (Backends.lowerExprNative (.call "mappingSlot" args)) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeExprPreservesWord_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves + name "mappingSlot" expected args + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + (by rfl) hArgs + (by + intro fuel state values final rets hLookup hCall + exact + native_mappingSlot_call_preserves_lookup_state name expected fuel + values dispatcher state final rets hLookup hCall) + +theorem NativeExprPreservesWord_lowerExprNative_of_bridgedExpr_mappingContract + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (expr : YulExpr) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hExpr : Compiler.Proofs.YulGeneration.Backends.BridgedExpr expr) : + NativeExprPreservesWord name expected + (Backends.lowerExprNative expr) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + induction hExpr with + | lit n => + exact NativeExprPreservesWord_lowerExprNative_lit name expected n _ + | hex n => + exact NativeExprPreservesWord_lowerExprNative_hex name expected n _ + | str s => + exact NativeExprPreservesWord_lowerExprNative_str name expected s _ + | ident ident => + exact NativeExprPreservesWord_lowerExprNative_ident name expected ident _ + | call func args hName hArgs ih => + have hNativeArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeEvalArgsPreservesWord_map_lowerExprNative_reverse + name expected args _ (by + intro arg hArg + exact ih arg hArg) + by_cases hMapping : func = "mappingSlot" + · subst func + exact + NativeExprPreservesWord_lowerExprNative_mappingSlot_of_nativeEvalArgs + name expected args dispatcher hNativeArgs + · cases hOp : Backends.lookupRuntimePrimOp func with + | some op => + exact + NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name func expected args op _ hOp hNativeArgs + (NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp + name func expected op hName hOp) + | none => + exfalso + unfold Backends.lookupRuntimePrimOp at hOp + split at hOp <;> simp at hOp + simp [Compiler.Proofs.YulGeneration.Backends.allowedExprCallName, + Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins, + hMapping] at hName + tauto + +theorem NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeEvalArgsPreservesWord_map_lowerExprNative_reverse + name expected args + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + (by + intro arg hArg + exact + NativeExprPreservesWord_lowerExprNative_of_bridgedExpr_mappingContract + name expected arg dispatcher (hArgs arg hArg)) + +/-- Mapping-free expression fragment for native matched-word preservation. + +This mirrors `BridgedExpr` but excludes `mappingSlot` calls recursively, so the +native proof can target the actual lowered runtime contract instead of the +synthetic mapping-helper contract. -/ +inductive NativeMappingFreeBridgedExpr : YulExpr → Prop + | lit (n : Nat) : NativeMappingFreeBridgedExpr (.lit n) + | hex (n : Nat) : NativeMappingFreeBridgedExpr (.hex n) + | str (s : String) : NativeMappingFreeBridgedExpr (.str s) + | ident (name : String) : NativeMappingFreeBridgedExpr (.ident name) + | call (func : String) (args : List YulExpr) + (hName : Compiler.Proofs.YulGeneration.Backends.allowedExprCallName func) + (hNoMapping : func ≠ "mappingSlot") + (hArgs : ∀ arg, arg ∈ args → NativeMappingFreeBridgedExpr arg) : + NativeMappingFreeBridgedExpr (.call func args) + +/-- Mapping-free bridged expressions preserve a marker word for any native +runtime contract override. + +The only user-function-shaped call admitted by the historical bridged +expression predicate is `mappingSlot`; excluding it leaves only runtime +primitive calls, whose preservation proof is contract-independent. -/ +theorem NativeExprPreservesWord_lowerExprNative_of_mappingFreeBridgedExpr + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (expr : YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hExpr : NativeMappingFreeBridgedExpr expr) : + NativeExprPreservesWord name expected + (Backends.lowerExprNative expr) codeOverride := by + induction hExpr with + | lit n => + exact NativeExprPreservesWord_lowerExprNative_lit name expected n _ + | hex n => + exact NativeExprPreservesWord_lowerExprNative_hex name expected n _ + | str s => + exact NativeExprPreservesWord_lowerExprNative_str name expected s _ + | ident ident => + exact NativeExprPreservesWord_lowerExprNative_ident name expected ident _ + | call func args hName hNoMapping hArgs ih => + have hNativeArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride := + NativeEvalArgsPreservesWord_map_lowerExprNative_reverse + name expected args codeOverride (by + intro arg hArg + exact ih arg hArg) + cases hOp : Backends.lookupRuntimePrimOp func with + | some op => + exact + NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name func expected args op codeOverride hOp hNativeArgs + (NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp + name func expected op hName hOp) + | none => + exfalso + unfold Backends.lookupRuntimePrimOp at hOp + split at hOp <;> simp at hOp + simp [Compiler.Proofs.YulGeneration.Backends.allowedExprCallName, + Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins, + hNoMapping] at hName + tauto + +theorem NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + ∀ arg, arg ∈ args → NativeMappingFreeBridgedExpr arg) : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride := + NativeEvalArgsPreservesWord_map_lowerExprNative_reverse + name expected args codeOverride (by + intro arg hArg + exact + NativeExprPreservesWord_lowerExprNative_of_mappingFreeBridgedExpr + name expected arg codeOverride (hArgs arg hArg)) + theorem nativeSwitchDiscrTempName_ne_matchedTempName (switchId : Nat) : Backends.nativeSwitchDiscrTempName switchId ≠ @@ -6454,8 +12760,83 @@ theorem nativeStmtWriteNames_not_mem_of_nativeStmtsWriteNames_not_mem | nil => simp at hMem | cons head tail ih => - simp [Backends.nativeStmtsWriteNames, - Backends.collectNativeStmtWriteNames] at hFresh hMem + simp [Backends.nativeStmtsWriteNames] at hFresh hMem + rcases hMem with hEq | hTail + · subst stmt + exact hFresh.1 + · exact ih hFresh.2 hTail + +theorem nativeStmtWriteNames_let_singleton_not_mem_ne + (name target : EvmYul.Identifier) + (value : Option EvmYul.Yul.Ast.Expr) + (hFresh : name ∉ Backends.nativeStmtWriteNames (.Let [target] value)) : + name ≠ target := by + intro hEq + subst hEq + simp [Backends.nativeStmtWriteNames] at hFresh + +theorem nativeStmtWriteNames_let_not_mem_vars + (name : EvmYul.Identifier) + (vars : List EvmYul.Identifier) + (value : Option EvmYul.Yul.Ast.Expr) + (hFresh : name ∉ Backends.nativeStmtWriteNames (.Let vars value)) : + name ∉ vars := by + simpa [Backends.nativeStmtWriteNames] using hFresh + +theorem nativeStmtWriteNames_lowerAssignNative_not_mem_ne + (name target : EvmYul.Identifier) + (value : YulExpr) + (hFresh : + name ∉ Backends.nativeStmtWriteNames + (Backends.lowerAssignNative target value)) : + name ≠ target := by + intro hEq + subst hEq + simp [Backends.nativeStmtWriteNames, Backends.lowerAssignNative] at hFresh + +theorem collectYulStmtWriteNames_append + (writeStmt : YulStmt → List String) + (left right : List YulStmt) : + Backends.collectYulStmtWriteNames writeStmt (left ++ right) = + Backends.collectYulStmtWriteNames writeStmt left ++ + Backends.collectYulStmtWriteNames writeStmt right := by + induction left with + | nil => + simp [Backends.collectYulStmtWriteNames] + | cons head tail ih => + simp [Backends.collectYulStmtWriteNames, ih, List.append_assoc] + +theorem yulStmtsWriteNames_append + (left right : List YulStmt) : + Backends.yulStmtsWriteNames (left ++ right) = + Backends.yulStmtsWriteNames left ++ Backends.yulStmtsWriteNames right := by + induction left with + | nil => + simp [Backends.yulStmtsWriteNames] + | cons head tail ih => + simp [Backends.yulStmtsWriteNames, ih, List.append_assoc] + +theorem yulStmtsWriteNames_cons + (stmt : YulStmt) + (rest : List YulStmt) : + Backends.yulStmtsWriteNames (stmt :: rest) = + Backends.yulStmtWriteNames stmt ++ Backends.yulStmtsWriteNames rest := by + simp [Backends.yulStmtsWriteNames] + +theorem yulStmtWriteNames_not_mem_of_yulStmtsWriteNames_not_mem + (name : EvmYul.Identifier) + (body : List YulStmt) + (stmt : YulStmt) + (hFresh : name ∉ Backends.yulStmtsWriteNames body) + (hMem : stmt ∈ body) : + name ∉ Backends.yulStmtWriteNames stmt := by + induction body with + | nil => + simp at hMem + | cons head tail ih => + rw [yulStmtsWriteNames_cons] at hFresh + simp only [List.mem_append, not_or] at hFresh + simp only [List.mem_cons] at hMem rcases hMem with hEq | hTail · subst stmt exact hFresh.1 @@ -6477,14 +12858,18 @@ theorem nativeStmtsWriteNames_append (left right : List EvmYul.Yul.Ast.Stmt) : Backends.nativeStmtsWriteNames (left ++ right) = Backends.nativeStmtsWriteNames left ++ Backends.nativeStmtsWriteNames right := by - simp [Backends.nativeStmtsWriteNames, collectNativeStmtWriteNames_append] + induction left with + | nil => + simp [Backends.nativeStmtsWriteNames] + | cons head tail ih => + simp [Backends.nativeStmtsWriteNames, ih, List.append_assoc] theorem nativeStmtsWriteNames_cons (stmt : EvmYul.Yul.Ast.Stmt) (rest : List EvmYul.Yul.Ast.Stmt) : Backends.nativeStmtsWriteNames (stmt :: rest) = Backends.nativeStmtWriteNames stmt ++ Backends.nativeStmtsWriteNames rest := by - simp [Backends.nativeStmtsWriteNames, Backends.collectNativeStmtWriteNames] + simp [Backends.nativeStmtsWriteNames] theorem nativeStmtsWriteNames_cons_not_mem_iff (name : EvmYul.Identifier) @@ -6840,6 +13225,248 @@ theorem NativeStmtPreservesWord_if_of_cond_preserves_and_nativeStmtsWriteNames_n (NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem name value body codeOverride hFresh hPreserves) +theorem nativeSwitchBranchFold_ok_preserves_word + (name : EvmYul.Identifier) + (value cond : EvmYul.Literal) + (branches : + List (EvmYul.Literal × Except EvmYul.Yul.Exception EvmYul.Yul.State)) + (defaultState final : EvmYul.Yul.State) + (hBranches : + ∀ tag branchState, (tag, .ok branchState) ∈ branches → + branchState[name]! = value) + (hDefault : defaultState[name]! = value) + (hFold : + List.foldr + (fun (valᵢ, sᵢ) s => if valᵢ = cond then sᵢ else s) + (.ok defaultState) branches = .ok final) : + final[name]! = value := by + induction branches with + | nil => + simp at hFold + cases hFold + exact hDefault + | cons head tail ih => + rcases head with ⟨tag, result⟩ + by_cases hEq : tag = cond + · simp [hEq] at hFold + cases result with + | error err => + simp at hFold + | ok branchState => + have hBranch : branchState[name]! = value := + hBranches tag branchState (by simp) + cases hFold + exact hBranch + · simp [hEq] at hFold + exact ih + (by + intro tag' branchState hMem + exact hBranches tag' branchState (by simp [hMem])) + hFold + +theorem execSwitchCases_ok_branch_preserves_word + (name : EvmYul.Identifier) (value : EvmYul.Literal) + (cases : List (EvmYul.Literal × List EvmYul.Yul.Ast.Stmt)) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hCases : ∀ tag body, (tag, body) ∈ cases → NativeBlockPreservesWord name value body codeOverride) : + ∀ fuel state branches, state[name]! = value → EvmYul.Yul.execSwitchCases fuel codeOverride state cases = .ok branches → + ∀ tag branchState, (tag, .ok branchState) ∈ branches → branchState[name]! = value := by + induction cases with + | nil => + intro fuel state branches _ hExec tag branchState hMem + simp [EvmYul.Yul.execSwitchCases] at hExec; subst branches; simp at hMem + | cons head tail ih => + intro fuel state branches hLookup hExec tag branchState hMem + rcases head with ⟨headTag, headBody⟩ + have hTailCases : ∀ tag' body', (tag', body') ∈ tail → + NativeBlockPreservesWord name value body' codeOverride := by + intro tag' body' hTailMem; exact hCases tag' body' (by simp [hTailMem]) + cases fuel with + | zero => simp [EvmYul.Yul.execSwitchCases] at hExec + | succ fuel' => + cases hHead : + EvmYul.Yul.exec fuel' (.Block headBody) codeOverride state with + | error err => + cases err <;> + cases hTail : + EvmYul.Yul.execSwitchCases fuel' codeOverride state tail with + | error tailErr => + simp [EvmYul.Yul.execSwitchCases, hHead, hTail] at hExec + | ok tailBranches => + simp [EvmYul.Yul.execSwitchCases, hHead, hTail] at hExec + subst branches + simp at hMem + exact ih hTailCases fuel' state tailBranches hLookup hTail + tag branchState hMem + | ok headState => + cases hTail : + EvmYul.Yul.execSwitchCases fuel' codeOverride state tail with + | error tailErr => + simp [EvmYul.Yul.execSwitchCases, hHead, hTail] at hExec + | ok tailBranches => + simp [EvmYul.Yul.execSwitchCases, hHead, hTail] at hExec + subst branches + simp at hMem + rcases hMem with hMem | hMem + · rcases hMem with ⟨rfl, rfl⟩ + exact hCases tag headBody (by simp) + fuel' state branchState hLookup hHead + · exact ih hTailCases fuel' state tailBranches hLookup hTail + tag branchState hMem + +theorem NativeStmtPreservesWord_switch_of_eval_preserves + (name : EvmYul.Identifier) (value : EvmYul.Literal) + (cond : EvmYul.Yul.Ast.Expr) + (cases : List (EvmYul.Literal × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hCond : + ∀ fuel state, + state[name]! = value → + ∃ condState condValue, + EvmYul.Yul.eval fuel cond codeOverride state = + .ok (condState, condValue) ∧ + condState[name]! = value) + (hCases : ∀ tag body, (tag, body) ∈ cases → + NativeBlockPreservesWord name value body codeOverride) + (hDefault : + NativeBlockPreservesWord name value defaultBody codeOverride) : + NativeStmtPreservesWord name value (.Switch cond cases defaultBody) + codeOverride := by + intro fuel state final hLookup hExec + cases fuel with + | zero => + simp [EvmYul.Yul.exec] at hExec + | succ fuel' => + rcases hCond fuel' state hLookup with + ⟨condState, condValue, hEval, hCondLookup⟩ + simp [EvmYul.Yul.exec, hEval] at hExec + cases hSwitch : + EvmYul.Yul.execSwitchCases fuel' codeOverride condState cases with + | error err => + simp [hSwitch] at hExec + | ok branches => + cases hDefaultExec : + EvmYul.Yul.exec fuel' (.Block defaultBody) codeOverride + condState with + | error err => + simp [hSwitch, hDefaultExec] at hExec + | ok defaultState => + simp [hSwitch, hDefaultExec] at hExec + exact nativeSwitchBranchFold_ok_preserves_word name value + condValue branches defaultState final + (execSwitchCases_ok_branch_preserves_word name value cases + codeOverride hCases fuel' condState branches hCondLookup + hSwitch) + (hDefault fuel' condState defaultState hCondLookup + hDefaultExec) + hExec + +theorem NativeStmtPreservesWord_switch_of_cond_preserves + (name : EvmYul.Identifier) (value : EvmYul.Literal) + (cond : EvmYul.Yul.Ast.Expr) + (cases : List (EvmYul.Literal × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hCond : NativeExprPreservesWord name value cond codeOverride) + (hCases : ∀ tag body, (tag, body) ∈ cases → + NativeBlockPreservesWord name value body codeOverride) + (hDefault : + NativeBlockPreservesWord name value defaultBody codeOverride) : + NativeStmtPreservesWord name value (.Switch cond cases defaultBody) + codeOverride := by + intro fuel state final hLookup hExec + cases fuel with + | zero => + simp [EvmYul.Yul.exec] at hExec + | succ fuel' => + simp [EvmYul.Yul.exec] at hExec + cases hEval : EvmYul.Yul.eval fuel' cond codeOverride state with + | error err => + simp [hEval] at hExec + | ok condResult => + rcases condResult with ⟨condState, condValue⟩ + have hCondLookup : condState[name]! = value := + hCond fuel' state condState condValue hLookup hEval + cases hSwitch : + EvmYul.Yul.execSwitchCases fuel' codeOverride condState cases with + | error err => + simp [hEval, hSwitch] at hExec + | ok branches => + cases hDefaultExec : + EvmYul.Yul.exec fuel' (.Block defaultBody) codeOverride + condState with + | error err => + simp [hEval, hSwitch, hDefaultExec] at hExec + | ok defaultState => + simp [hEval, hSwitch, hDefaultExec] at hExec + exact nativeSwitchBranchFold_ok_preserves_word name value + condValue branches defaultState final + (execSwitchCases_ok_branch_preserves_word name value cases + codeOverride hCases fuel' condState branches hCondLookup + hSwitch) + (hDefault fuel' condState defaultState hCondLookup + hDefaultExec) + hExec + +theorem NativeStmtPreservesWord_switch_of_cond_preserves_and_nativeStmtsWriteNames_not_mem + (name : EvmYul.Identifier) (value : EvmYul.Literal) + (cond : EvmYul.Yul.Ast.Expr) + (cases : List (EvmYul.Literal × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hCond : NativeExprPreservesWord name value cond codeOverride) + (hCasesFresh : ∀ tag body, (tag, body) ∈ cases → + name ∉ Backends.nativeStmtsWriteNames body) + (hDefaultFresh : name ∉ Backends.nativeStmtsWriteNames defaultBody) + (hPreserves : + ∀ stmt, name ∉ Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord name value stmt codeOverride) : + NativeStmtPreservesWord name value (.Switch cond cases defaultBody) + codeOverride := + NativeStmtPreservesWord_switch_of_cond_preserves name value cond cases + defaultBody codeOverride hCond + (by + intro tag body hMem + exact NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem + name value body codeOverride (hCasesFresh tag body hMem) + (by intro stmt _ hFresh; exact hPreserves stmt hFresh)) + (NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem + name value defaultBody codeOverride hDefaultFresh + (by intro stmt _ hFresh; exact hPreserves stmt hFresh)) + +theorem NativeStmtPreservesWord_switch_of_eval_preserves_and_nativeStmtsWriteNames_not_mem + (name : EvmYul.Identifier) (value : EvmYul.Literal) + (cond : EvmYul.Yul.Ast.Expr) + (cases : List (EvmYul.Literal × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hCond : + ∀ fuel state, + state[name]! = value → + ∃ condState condValue, + EvmYul.Yul.eval fuel cond codeOverride state = + .ok (condState, condValue) ∧ + condState[name]! = value) + (hCasesFresh : ∀ tag body, (tag, body) ∈ cases → + name ∉ Backends.nativeStmtsWriteNames body) + (hDefaultFresh : name ∉ Backends.nativeStmtsWriteNames defaultBody) + (hPreserves : + ∀ stmt, name ∉ Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord name value stmt codeOverride) : + NativeStmtPreservesWord name value (.Switch cond cases defaultBody) + codeOverride := + NativeStmtPreservesWord_switch_of_eval_preserves name value cond cases + defaultBody codeOverride hCond + (by + intro tag body hMem + exact NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem + name value body codeOverride (hCasesFresh tag body hMem) + (by intro stmt _ hFresh; exact hPreserves stmt hFresh)) + (NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem + name value defaultBody codeOverride hDefaultFresh + (by intro stmt _ hFresh; exact hPreserves stmt hFresh)) + theorem NativeStmtPreservesWord_lowerAssignNative_lit_of_ne (name target : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7133,6 +13760,42 @@ theorem NativeStmtPreservesWord_let_user_of_evalArgs_call_preserves rw [state_getElem_multifill_of_not_mem callState name vars rets hnot] exact hCallLookup +theorem NativeStmtPreservesWord_let_prim_of_nativeEvalArgs_primCall_preserves + (name : EvmYul.Identifier) (expected : EvmYul.Literal) + (vars : List EvmYul.Identifier) (prim : EvmYul.Yul.Ast.PrimOp) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hnot : name ∉ vars) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hPrim : + ∀ fuel state values primState rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state prim values = .ok (primState, rets) → + primState[name]! = expected) : + NativeStmtPreservesWord name expected + (.Let vars (some (.Call (Sum.inl prim) args))) codeOverride := + NativeStmtPreservesWord_let_prim_of_evalArgs_primCall_preserves + name expected vars prim args codeOverride hnot hArgs hPrim + +theorem NativeStmtPreservesWord_let_user_of_nativeEvalArgs_call_preserves + (name : EvmYul.Identifier) (expected : EvmYul.Literal) + (vars : List EvmYul.Identifier) + (functionName : EvmYul.Yul.Ast.YulFunctionName) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hnot : name ∉ vars) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hCall : + ∀ fuel state values callState rets, + state[name]! = expected → + EvmYul.Yul.call fuel values (some functionName) codeOverride state = + .ok (callState, rets) → + callState[name]! = expected) : + NativeStmtPreservesWord name expected + (.Let vars (some (.Call (Sum.inr functionName) args))) codeOverride := + NativeStmtPreservesWord_let_user_of_evalArgs_call_preserves + name expected vars functionName args codeOverride hnot hArgs hCall + theorem NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves (name func : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7237,8 +13900,41 @@ theorem NativeStmtPreservesWord_let_lowerExprNative_call_userFunction_of_nativeE NativeStmtPreservesWord_let_lowerExprNative_call_userFunction_of_evalArgs_call_preserves name func expected vars args codeOverride hnot hOp hArgs hCall -theorem NativeStmtPreservesWord_lowerAssignNative_call_runtimePrimOp_of_evalArgs_primCall_preserves - (name target func : EvmYul.Identifier) +theorem NativeStmtPreservesWord_let_lowerExprNative_mappingSlot_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (vars : List EvmYul.Identifier) + (args : List YulExpr) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hnot : name ∉ vars) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) })) : + NativeStmtPreservesWord name expected + (.Let vars (some (Backends.lowerExprNative (.call "mappingSlot" args)))) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeStmtPreservesWord_let_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves + name "mappingSlot" expected vars args + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + hnot (by rfl) hArgs + (by + intro fuel state values callState rets hLookup hCall + exact + native_mappingSlot_call_preserves_lookup_state name expected fuel + values dispatcher state callState rets hLookup hCall) + +theorem NativeStmtPreservesWord_lowerAssignNative_call_runtimePrimOp_of_evalArgs_primCall_preserves + (name target func : EvmYul.Identifier) (expected : EvmYul.Literal) (args : List YulExpr) (op : EvmYul.Operation .Yul) @@ -7335,6 +14031,499 @@ theorem NativeStmtPreservesWord_lowerAssignNative_call_userFunction_of_nativeEva NativeStmtPreservesWord_lowerAssignNative_call_userFunction_of_evalArgs_call_preserves name target func expected args codeOverride hne hOp hArgs hCall +theorem NativeStmtPreservesWord_let_lowerExprNative_of_mappingFreeBridgedExpr + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (target : EvmYul.Identifier) + (value : YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hne : name ≠ target) + (hValue : NativeMappingFreeBridgedExpr value) : + NativeStmtPreservesWord name expected + (.Let [target] (some (Backends.lowerExprNative value))) codeOverride := by + cases value with + | lit n => + exact + NativeStmtPreservesWord_let_lowerExprNative_lit_of_not_mem + name expected [target] n codeOverride (by simp) (by simpa using hne) + | hex n => + exact + NativeStmtPreservesWord_let_lowerExprNative_hex_of_not_mem + name expected [target] n codeOverride (by simp) (by simpa using hne) + | str s => + exact + NativeStmtPreservesWord_let_lowerExprNative_str_of_not_mem + name expected [target] s codeOverride (by simp) (by simpa using hne) + | ident ident => + exact + NativeStmtPreservesWord_let_lowerExprNative_ident_of_not_mem + name expected [target] ident codeOverride (by simp) (by simpa using hne) + | call func args => + cases hValue with + | call _ _ hName hNoMapping hArgs => + have hNativeArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride := + NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected args codeOverride hArgs + cases hOp : Backends.lookupRuntimePrimOp func with + | some op => + exact + NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name func expected [target] args op codeOverride + (by simp [hne]) hOp hNativeArgs + (NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp + name func expected op hName hOp) + | none => + exfalso + unfold Backends.lookupRuntimePrimOp at hOp + split at hOp <;> simp at hOp + simp [Compiler.Proofs.YulGeneration.Backends.allowedExprCallName, + Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins, + hNoMapping] at hName + tauto + +theorem NativeStmtPreservesWord_letMany_lowerExprNative_of_mappingFreeBridgedExpr + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (vars : List EvmYul.Identifier) + (value : YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hvars : vars ≠ []) + (hnot : name ∉ vars) + (hValue : NativeMappingFreeBridgedExpr value) : + NativeStmtPreservesWord name expected + (.Let vars (some (Backends.lowerExprNative value))) codeOverride := by + cases value with + | lit n => + exact + NativeStmtPreservesWord_let_lowerExprNative_lit_of_not_mem + name expected vars n codeOverride hvars hnot + | hex n => + exact + NativeStmtPreservesWord_let_lowerExprNative_hex_of_not_mem + name expected vars n codeOverride hvars hnot + | str s => + exact + NativeStmtPreservesWord_let_lowerExprNative_str_of_not_mem + name expected vars s codeOverride hvars hnot + | ident ident => + exact + NativeStmtPreservesWord_let_lowerExprNative_ident_of_not_mem + name expected vars ident codeOverride hvars hnot + | call func args => + cases hValue with + | call _ _ hName hNoMapping hArgs => + have hNativeArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride := + NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected args codeOverride hArgs + cases hOp : Backends.lookupRuntimePrimOp func with + | some op => + exact + NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name func expected vars args op codeOverride hnot hOp + hNativeArgs + (NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp + name func expected op hName hOp) + | none => + exfalso + unfold Backends.lookupRuntimePrimOp at hOp + split at hOp <;> simp at hOp + simp [Compiler.Proofs.YulGeneration.Backends.allowedExprCallName, + Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins, + hNoMapping] at hName + tauto + +theorem NativeStmtPreservesWord_lowerAssignNative_of_mappingFreeBridgedExpr + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (target : EvmYul.Identifier) + (value : YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hne : name ≠ target) + (hValue : NativeMappingFreeBridgedExpr value) : + NativeStmtPreservesWord name expected + (Backends.lowerAssignNative target value) codeOverride := by + simpa [Backends.lowerAssignNative] using + NativeStmtPreservesWord_let_lowerExprNative_of_mappingFreeBridgedExpr + name expected target value codeOverride hne hValue + +theorem NativeStmtPreservesWord_lowerAssignNative_mappingSlot_of_nativeEvalArgs + (name target : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hne : name ≠ target) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) })) : + NativeStmtPreservesWord name expected + (Backends.lowerAssignNative target (.call "mappingSlot" args)) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeStmtPreservesWord_lowerAssignNative_call_userFunction_of_nativeEvalArgs_call_preserves + name target "mappingSlot" expected args + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + hne (by rfl) hArgs + (by + intro fuel state values callState rets hLookup hCall + exact + native_mappingSlot_call_preserves_lookup_state name expected fuel + values dispatcher state callState rets hLookup hCall) + +theorem NativeStmtPreservesWord_let_lowerExprNative_of_bridgedExpr_mappingContract + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (target : EvmYul.Identifier) + (value : YulExpr) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hne : name ≠ target) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) : + NativeStmtPreservesWord name expected + (.Let [target] (some (Backends.lowerExprNative value))) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + cases value with + | lit n => + exact + NativeStmtPreservesWord_let_lowerExprNative_lit_of_not_mem + name expected [target] n _ (by simp) (by simpa using hne) + | hex n => + exact + NativeStmtPreservesWord_let_lowerExprNative_hex_of_not_mem + name expected [target] n _ (by simp) (by simpa using hne) + | str s => + exact + NativeStmtPreservesWord_let_lowerExprNative_str_of_not_mem + name expected [target] s _ (by simp) (by simpa using hne) + | ident ident => + exact + NativeStmtPreservesWord_let_lowerExprNative_ident_of_not_mem + name expected [target] ident _ (by simp) (by simpa using hne) + | call func args => + cases hValue with + | call _ _ hName hArgs => + have hNativeArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs + by_cases hMapping : func = "mappingSlot" + · subst func + exact + NativeStmtPreservesWord_let_lowerExprNative_mappingSlot_of_nativeEvalArgs + name expected [target] args dispatcher (by simp [hne]) + hNativeArgs + · cases hOp : Backends.lookupRuntimePrimOp func with + | some op => + exact + NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name func expected [target] args op _ (by simp [hne]) hOp + hNativeArgs + (NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp + name func expected op hName hOp) + | none => + exfalso + unfold Backends.lookupRuntimePrimOp at hOp + split at hOp <;> simp at hOp + simp [Compiler.Proofs.YulGeneration.Backends.allowedExprCallName, + Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins, + hMapping] at hName + tauto + +theorem NativeStmtPreservesWord_letMany_lowerExprNative_of_bridgedExpr_mappingContract + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (vars : List EvmYul.Identifier) + (value : YulExpr) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hvars : vars ≠ []) + (hnot : name ∉ vars) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) : + NativeStmtPreservesWord name expected + (.Let vars (some (Backends.lowerExprNative value))) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + cases value with + | lit n => + exact + NativeStmtPreservesWord_let_lowerExprNative_lit_of_not_mem + name expected vars n _ hvars hnot + | hex n => + exact + NativeStmtPreservesWord_let_lowerExprNative_hex_of_not_mem + name expected vars n _ hvars hnot + | str s => + exact + NativeStmtPreservesWord_let_lowerExprNative_str_of_not_mem + name expected vars s _ hvars hnot + | ident ident => + exact + NativeStmtPreservesWord_let_lowerExprNative_ident_of_not_mem + name expected vars ident _ hvars hnot + | call func args => + cases hValue with + | call _ _ hName hArgs => + have hNativeArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs + by_cases hMapping : func = "mappingSlot" + · subst func + exact + NativeStmtPreservesWord_let_lowerExprNative_mappingSlot_of_nativeEvalArgs + name expected vars args dispatcher hnot hNativeArgs + · cases hOp : Backends.lookupRuntimePrimOp func with + | some op => + exact + NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name func expected vars args op _ hnot hOp + hNativeArgs + (NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp + name func expected op hName hOp) + | none => + exfalso + unfold Backends.lookupRuntimePrimOp at hOp + split at hOp <;> simp at hOp + simp [Compiler.Proofs.YulGeneration.Backends.allowedExprCallName, + Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins, + hMapping] at hName + tauto + +theorem NativeStmtPreservesWord_lowerAssignNative_of_bridgedExpr_mappingContract + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (target : EvmYul.Identifier) + (value : YulExpr) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hne : name ≠ target) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) : + NativeStmtPreservesWord name expected + (Backends.lowerAssignNative target value) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + simpa [Backends.lowerAssignNative] using + NativeStmtPreservesWord_let_lowerExprNative_of_bridgedExpr_mappingContract + name expected target value dispatcher hne hValue + +theorem NativeStmtPreservesWord_empty_block + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) : + NativeStmtPreservesWord name expected (.Block []) codeOverride := + NativeStmtPreservesWord_block name expected [] codeOverride + (NativeBlockPreservesWord_nil name expected codeOverride) + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_comment + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (text : String) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.comment text) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_comment] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact NativeStmtPreservesWord_empty_block name expected _ + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_let + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (target : EvmYul.Identifier) + (value : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.let_ target value) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hne : name ≠ target) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_let] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_let_lowerExprNative_of_bridgedExpr_mappingContract + name expected target value dispatcher hne hValue + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_let_of_write_not_mem + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (target : EvmYul.Identifier) + (value : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.let_ target value) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hFresh : name ∉ Backends.nativeStmtWriteNames nativeStmt) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_let] at hLower + cases hLower + simp at hMem + subst nativeStmt + refine + NativeStmtPreservesWord_let_lowerExprNative_of_bridgedExpr_mappingContract + name expected target value dispatcher + (nativeStmtWriteNames_let_singleton_not_mem_ne name target + (some (Backends.lowerExprNative value)) hFresh) + hValue + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_letMany_of_write_not_mem + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (targets : List EvmYul.Identifier) + (value : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hTargets : targets ≠ []) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.letMany targets value) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hFresh : name ∉ Backends.nativeStmtWriteNames nativeStmt) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_letMany] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_letMany_lowerExprNative_of_bridgedExpr_mappingContract + name expected targets value dispatcher hTargets + (nativeStmtWriteNames_let_not_mem_vars name targets + (some (Backends.lowerExprNative value)) hFresh) + hValue + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_assign + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (target : EvmYul.Identifier) + (value : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.assign target value) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hne : name ≠ target) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_assign] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_lowerAssignNative_of_bridgedExpr_mappingContract + name expected target value dispatcher hne hValue + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_assign_of_write_not_mem + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (target : EvmYul.Identifier) + (value : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.assign target value) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hFresh : name ∉ Backends.nativeStmtWriteNames nativeStmt) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_assign] at hLower + cases hLower + simp at hMem + subst nativeStmt + refine + NativeStmtPreservesWord_lowerAssignNative_of_bridgedExpr_mappingContract + name expected target value dispatcher + (nativeStmtWriteNames_lowerAssignNative_not_mem_ne name target value hFresh) + hValue + theorem NativeStmtPreservesWord_exprStmtCall_prim_of_evalArgs_primCall_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7428,6 +14617,41 @@ theorem NativeStmtPreservesWord_exprStmtCall_user_of_evalArgs_call_preserves hArgLookup hUserCall cases callState <;> simpa using hCallLookup +theorem NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (prim : EvmYul.Yul.Ast.PrimOp) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hPrim : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.primCall fuel state prim values = .ok (final, rets) → + final[name]! = expected) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl prim) args)) codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_evalArgs_primCall_preserves + name expected prim args codeOverride hArgs hPrim + +theorem NativeStmtPreservesWord_exprStmtCall_user_of_nativeEvalArgs_call_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (functionName : EvmYul.Yul.Ast.YulFunctionName) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hCall : + ∀ fuel state values final rets, + state[name]! = expected → + EvmYul.Yul.call fuel values (some functionName) codeOverride state = + .ok (final, rets) → + final[name]! = expected) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inr functionName) args)) codeOverride := + NativeStmtPreservesWord_exprStmtCall_user_of_evalArgs_call_preserves + name expected functionName args codeOverride hArgs hCall + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves (name func : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7524,6 +14748,95 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_userFunction_o NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_userFunction_of_evalArgs_call_preserves name func expected args codeOverride hOp hArgs hCall +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mappingSlot_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) })) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "mappingSlot" args))) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves + name "mappingSlot" expected args + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + (by rfl) hArgs + (by + intro fuel state values final rets hLookup hCall + exact + native_mappingSlot_call_preserves_lookup_state name expected fuel + values dispatcher state final rets hLookup hCall) + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_call_of_bridgedExpr_mappingContract + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (func : EvmYul.Identifier) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hName : Compiler.Proofs.YulGeneration.Backends.allowedExprCallName func) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call func args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + have hNativeArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs + by_cases hMapping : func = "mappingSlot" + · subst func + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mappingSlot_of_nativeEvalArgs + name expected args dispatcher hNativeArgs + · cases hOp : Backends.lookupRuntimePrimOp func with + | some op => + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name func expected args op _ hOp hNativeArgs + (NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp + name func expected op hName hOp) + | none => + exfalso + unfold Backends.lookupRuntimePrimOp at hOp + split at hOp <;> simp at hOp + simp [Compiler.Proofs.YulGeneration.Backends.allowedExprCallName, + Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins, + hMapping] at hName + tauto + theorem NativeStmtPreservesWord_exprStmtCall_mstore_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7564,6 +14877,43 @@ theorem NativeStmtPreservesWord_exprStmtCall_mstore_of_evalArgs_preserves cases jump <;> simpa [EvmYul.Yul.State.setMachineState] using hArgLookup +theorem NativeStmtPreservesWord_exprStmtCall_mstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset value, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [value, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.MSTORE) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_mstore_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, value, hEval⟩ + exact ⟨argState, offset, value, hEval, + hArgs fuel state argState [value, offset] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_mstore_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.MSTORE) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.MSTORE args codeOverride hArgs + (NativePrimCallPreservesWord_mstore_values name expected) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7585,6 +14935,49 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_evalArgs_ exact NativeStmtPreservesWord_exprStmtCall_mstore_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset value, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [value, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "mstore" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, value, hEval⟩ + exact ⟨argState, offset, value, hEval, + hArgs fuel state argState [value, offset] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "mstore" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "mstore" args + EvmYul.Operation.MSTORE (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_mstore_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + theorem NativeStmtPreservesWord_exprStmtCall_mstore8_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7625,6 +15018,43 @@ theorem NativeStmtPreservesWord_exprStmtCall_mstore8_of_evalArgs_preserves cases jump <;> simpa [EvmYul.Yul.State.setMachineState] using hArgLookup +theorem NativeStmtPreservesWord_exprStmtCall_mstore8_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset value, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [value, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.MSTORE8) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_mstore8_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, value, hEval⟩ + exact ⟨argState, offset, value, hEval, + hArgs fuel state argState [value, offset] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_mstore8_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.MSTORE8) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.MSTORE8 args codeOverride hArgs + (NativePrimCallPreservesWord_mstore8_values name expected) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7646,6 +15076,49 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_evalArgs exact NativeStmtPreservesWord_exprStmtCall_mstore8_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset value, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [value, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "mstore8" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, value, hEval⟩ + exact ⟨argState, offset, value, hEval, + hArgs fuel state argState [value, offset] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "mstore8" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "mstore8" args + EvmYul.Operation.MSTORE8 (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_mstore8_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + theorem NativeStmtPreservesWord_exprStmtCall_sstore_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7690,6 +15163,43 @@ theorem NativeStmtPreservesWord_exprStmtCall_sstore_of_evalArgs_preserves cases jump <;> simpa [EvmYul.Yul.State.setState] using hArgLookup +theorem NativeStmtPreservesWord_exprStmtCall_sstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState slot value, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [value, slot])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.SSTORE) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_sstore_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, slot, value, hEval⟩ + exact ⟨argState, slot, value, hEval, + hArgs fuel state argState [value, slot] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_sstore_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.SSTORE) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.SSTORE args codeOverride hArgs + (NativePrimCallPreservesWord_sstore_values name expected) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7711,18 +15221,61 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_evalArgs_ exact NativeStmtPreservesWord_exprStmtCall_sstore_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs -theorem NativeStmtPreservesWord_exprStmtCall_tstore_of_evalArgs_preserves +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_nativeEvalArgs_and_evalArgs_shape_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) - (args : List EvmYul.Yul.Ast.Expr) + (args : List YulExpr) (codeOverride : Option EvmYul.Yul.Ast.YulContract) (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : ∀ fuel state, state[name]! = expected → ∃ argState slot value, - EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = - .ok (argState, [value, slot]) ∧ - argState[name]! = expected) : + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [value, slot])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "sstore" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, slot, value, hEval⟩ + exact ⟨argState, slot, value, hEval, + hArgs fuel state argState [value, slot] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "sstore" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "sstore" args + EvmYul.Operation.SSTORE (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_sstore_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + +theorem NativeStmtPreservesWord_exprStmtCall_tstore_of_evalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + ∀ fuel state, + state[name]! = expected → + ∃ argState slot value, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [value, slot]) ∧ + argState[name]! = expected) : NativeStmtPreservesWord name expected (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.TSTORE) args)) codeOverride := by @@ -7755,6 +15308,43 @@ theorem NativeStmtPreservesWord_exprStmtCall_tstore_of_evalArgs_preserves cases jump <;> simpa [EvmYul.Yul.State.setState] using hArgLookup +theorem NativeStmtPreservesWord_exprStmtCall_tstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState slot value, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [value, slot])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.TSTORE) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_tstore_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, slot, value, hEval⟩ + exact ⟨argState, slot, value, hEval, + hArgs fuel state argState [value, slot] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_tstore_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.TSTORE) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.TSTORE args codeOverride hArgs + (NativePrimCallPreservesWord_tstore_values name expected) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7776,6 +15366,49 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_evalArgs_ exact NativeStmtPreservesWord_exprStmtCall_tstore_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState slot value, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [value, slot])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "tstore" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, slot, value, hEval⟩ + exact ⟨argState, slot, value, hEval, + hArgs fuel state argState [value, slot] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "tstore" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "tstore" args + EvmYul.Operation.TSTORE (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_tstore_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + theorem NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7816,6 +15449,30 @@ theorem NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_evalArgs_preserves cases jump <;> simpa [EvmYul.Yul.State.setSharedState] using hArgLookup +theorem NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState mstart datastart size, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [size, datastart, mstart])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.CALLDATACOPY) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, mstart, datastart, size, hEval⟩ + exact ⟨argState, mstart, datastart, size, hEval, + hArgs fuel state argState [size, datastart, mstart] hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7837,6 +15494,33 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_eva exact NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState mstart datastart size, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [size, datastart, mstart])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "calldatacopy" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, mstart, datastart, size, hEval⟩ + exact ⟨argState, mstart, datastart, size, hEval, + hArgs fuel state argState [size, datastart, mstart] hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7877,6 +15561,30 @@ theorem NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_evalArgs_preserve cases jump <;> simpa [EvmYul.Yul.State.setMachineState] using hArgLookup +theorem NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState mstart rstart size, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [size, rstart, mstart])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.RETURNDATACOPY) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, mstart, rstart, size, hEval⟩ + exact ⟨argState, mstart, rstart, size, hEval, + hArgs fuel state argState [size, rstart, mstart] hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7898,6 +15606,91 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_e exact NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState mstart rstart size, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [size, rstart, mstart])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "returndatacopy" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, mstart, rstart, size, hEval⟩ + exact ⟨argState, mstart, rstart, size, hEval, + hArgs fuel state argState [size, rstart, mstart] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.CALLDATACOPY) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.CALLDATACOPY args codeOverride hArgs + (NativePrimCallPreservesWord_calldatacopy_values name expected) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "calldatacopy" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "calldatacopy" args + EvmYul.Operation.CALLDATACOPY (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + +theorem NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.RETURNDATACOPY) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.RETURNDATACOPY args codeOverride hArgs + (NativePrimCallPreservesWord_returndatacopy_values name expected) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "returndatacopy" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "returndatacopy" args + EvmYul.Operation.RETURNDATACOPY (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + theorem NativeStmtPreservesWord_exprStmtCall_log0_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7942,6 +15735,30 @@ theorem NativeStmtPreservesWord_exprStmtCall_log0_of_evalArgs_preserves cases jump <;> simpa [EvmYul.Yul.State.setSharedState] using hArgLookup +theorem NativeStmtPreservesWord_exprStmtCall_log0_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.LOG0) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_log0_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, hEval⟩ + exact ⟨argState, offset, size, hEval, + hArgs fuel state argState [size, offset] hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -7963,6 +15780,33 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_evalArgs_pr exact NativeStmtPreservesWord_exprStmtCall_log0_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "log0" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, hEval⟩ + exact ⟨argState, offset, size, hEval, + hArgs fuel state argState [size, offset] hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_log1_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8007,6 +15851,30 @@ theorem NativeStmtPreservesWord_exprStmtCall_log1_of_evalArgs_preserves cases jump <;> simpa [EvmYul.Yul.State.setSharedState] using hArgLookup +theorem NativeStmtPreservesWord_exprStmtCall_log1_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [topic0, size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.LOG1) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_log1_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, topic0, hEval⟩ + exact ⟨argState, offset, size, topic0, hEval, + hArgs fuel state argState [topic0, size, offset] hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8028,6 +15896,33 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_evalArgs_pr exact NativeStmtPreservesWord_exprStmtCall_log1_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [topic0, size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "log1" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, topic0, hEval⟩ + exact ⟨argState, offset, size, topic0, hEval, + hArgs fuel state argState [topic0, size, offset] hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_log2_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8072,16 +15967,40 @@ theorem NativeStmtPreservesWord_exprStmtCall_log2_of_evalArgs_preserves cases jump <;> simpa [EvmYul.Yul.State.setSharedState] using hArgLookup -theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_evalArgs_preserves +theorem NativeStmtPreservesWord_exprStmtCall_log2_of_nativeEvalArgs_and_evalArgs_shape_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) - (args : List YulExpr) + (args : List EvmYul.Yul.Ast.Expr) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (hArgs : + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : ∀ fuel state, state[name]! = expected → ∃ argState offset size topic0 topic1, - EvmYul.Yul.evalArgs fuel + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [topic1, topic0, size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.LOG2) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_log2_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, topic0, topic1, hEval⟩ + exact ⟨argState, offset, size, topic0, topic1, hEval, + hArgs fuel state argState [topic1, topic0, size, offset] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_evalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0 topic1, + EvmYul.Yul.evalArgs fuel ((args.map Backends.lowerExprNative).reverse) codeOverride state = .ok (argState, [topic1, topic0, size, offset]) ∧ argState[name]! = expected) : @@ -8093,6 +16012,33 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_evalArgs_pr exact NativeStmtPreservesWord_exprStmtCall_log2_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0 topic1, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [topic1, topic0, size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "log2" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, topic0, topic1, hEval⟩ + exact ⟨argState, offset, size, topic0, topic1, hEval, + hArgs fuel state argState [topic1, topic0, size, offset] hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_log3_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8137,6 +16083,31 @@ theorem NativeStmtPreservesWord_exprStmtCall_log3_of_evalArgs_preserves cases jump <;> simpa [EvmYul.Yul.State.setSharedState] using hArgLookup +theorem NativeStmtPreservesWord_exprStmtCall_log3_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0 topic1 topic2, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [topic2, topic1, topic0, size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.LOG3) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_log3_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, topic0, topic1, topic2, hEval⟩ + exact ⟨argState, offset, size, topic0, topic1, topic2, hEval, + hArgs fuel state argState [topic2, topic1, topic0, size, offset] + hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8158,6 +16129,34 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_evalArgs_pr exact NativeStmtPreservesWord_exprStmtCall_log3_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0 topic1 topic2, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [topic2, topic1, topic0, size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "log3" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, topic0, topic1, topic2, hEval⟩ + exact ⟨argState, offset, size, topic0, topic1, topic2, hEval, + hArgs fuel state argState [topic2, topic1, topic0, size, offset] + hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_log4_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8202,6 +16201,31 @@ theorem NativeStmtPreservesWord_exprStmtCall_log4_of_evalArgs_preserves cases jump <;> simpa [EvmYul.Yul.State.setSharedState] using hArgLookup +theorem NativeStmtPreservesWord_exprStmtCall_log4_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0 topic1 topic2 topic3, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [topic3, topic2, topic1, topic0, size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.LOG4) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_log4_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, topic0, topic1, topic2, topic3, hEval⟩ + exact ⟨argState, offset, size, topic0, topic1, topic2, topic3, hEval, + hArgs fuel state argState + [topic3, topic2, topic1, topic0, size, offset] hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8223,6 +16247,179 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_evalArgs_pr exact NativeStmtPreservesWord_exprStmtCall_log4_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0 topic1 topic2 topic3, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [topic3, topic2, topic1, topic0, size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "log4" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, topic0, topic1, topic2, topic3, hEval⟩ + exact ⟨argState, offset, size, topic0, topic1, topic2, topic3, hEval, + hArgs fuel state argState + [topic3, topic2, topic1, topic0, size, offset] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_log0_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.LOG0) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.LOG0 args codeOverride hArgs + (NativePrimCallPreservesWord_log0_values name expected) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "log0" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "log0" args + EvmYul.Operation.LOG0 (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_log0_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + +theorem NativeStmtPreservesWord_exprStmtCall_log1_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.LOG1) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.LOG1 args codeOverride hArgs + (NativePrimCallPreservesWord_log1_values name expected) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "log1" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "log1" args + EvmYul.Operation.LOG1 (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_log1_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + +theorem NativeStmtPreservesWord_exprStmtCall_log2_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.LOG2) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.LOG2 args codeOverride hArgs + (NativePrimCallPreservesWord_log2_values name expected) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "log2" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "log2" args + EvmYul.Operation.LOG2 (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_log2_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + +theorem NativeStmtPreservesWord_exprStmtCall_log3_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.LOG3) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.LOG3 args codeOverride hArgs + (NativePrimCallPreservesWord_log3_values name expected) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "log3" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "log3" args + EvmYul.Operation.LOG3 (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_log3_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + +theorem NativeStmtPreservesWord_exprStmtCall_log4_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.LOG4) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.LOG4 args codeOverride hArgs + (NativePrimCallPreservesWord_log4_values name expected) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "log4" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "log4" args + EvmYul.Operation.LOG4 (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_log4_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + theorem NativeStmtPreservesWord_exprStmtCall_return_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8261,6 +16458,30 @@ theorem NativeStmtPreservesWord_exprStmtCall_return_of_evalArgs_preserves rcases ret with ⟨returnState, value⟩ simp [hReturn] at hExec +theorem NativeStmtPreservesWord_exprStmtCall_return_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.RETURN) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_return_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, hEval⟩ + exact ⟨argState, offset, size, hEval, + hArgs fuel state argState [size, offset] hLookup hEval⟩) + theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8282,6 +16503,62 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_evalArgs_ exact NativeStmtPreservesWord_exprStmtCall_return_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "return" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, hEval⟩ + exact ⟨argState, offset, size, hEval, + hArgs fuel state argState [size, offset] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_return_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.RETURN) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.RETURN args codeOverride hArgs + (NativePrimCallPreservesWord_return_values name expected) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "return" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "return" args + EvmYul.Operation.RETURN (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_return_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + theorem NativeStmtPreservesWord_exprStmtCall_revert_of_evalArgs_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8320,12 +16597,36 @@ theorem NativeStmtPreservesWord_exprStmtCall_revert_of_evalArgs_preserves rcases ret with ⟨revertState, value⟩ simp [hRevert] at hExec -theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_evalArgs_preserves +theorem NativeStmtPreservesWord_exprStmtCall_revert_of_nativeEvalArgs_and_evalArgs_shape_preserves (name : EvmYul.Identifier) (expected : EvmYul.Literal) - (args : List YulExpr) + (args : List EvmYul.Yul.Ast.Expr) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (hArgs : + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size, + EvmYul.Yul.evalArgs fuel args.reverse codeOverride state = + .ok (argState, [size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.REVERT) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_revert_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, hEval⟩ + exact ⟨argState, offset, size, hEval, + hArgs fuel state argState [size, offset] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_evalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : ∀ fuel state, state[name]! = expected → ∃ argState offset size, @@ -8341,6 +16642,62 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_evalArgs_ exact NativeStmtPreservesWord_exprStmtCall_revert_of_evalArgs_preserves name expected (args.map Backends.lowerExprNative) codeOverride hArgs +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_nativeEvalArgs_and_evalArgs_shape_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) codeOverride state = + .ok (argState, [size, offset])) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "revert" args))) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_evalArgs_preserves + name expected args codeOverride + (by + intro fuel state hLookup + rcases hShape fuel state hLookup with + ⟨argState, offset, size, hEval⟩ + exact ⟨argState, offset, size, hEval, + hArgs fuel state argState [size, offset] hLookup hEval⟩) + +theorem NativeStmtPreservesWord_exprStmtCall_revert_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List EvmYul.Yul.Ast.Expr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : NativeEvalArgsPreservesWord name expected args.reverse codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (.Call (Sum.inl EvmYul.Operation.REVERT) args)) + codeOverride := + NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + name expected EvmYul.Operation.REVERT args codeOverride hArgs + (NativePrimCallPreservesWord_revert_values name expected) + +theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_nativeEvalArgs_preserves + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (args : List YulExpr) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride) : + NativeStmtPreservesWord name expected + (.ExprStmtCall (Backends.lowerExprNative (.call "revert" args))) + codeOverride := by + rw [Backends.lowerExprNative_call_runtimePrimOp "revert" args + EvmYul.Operation.REVERT (by rfl)] + exact NativeStmtPreservesWord_exprStmtCall_revert_of_nativeEvalArgs_preserves + name expected (args.map Backends.lowerExprNative) codeOverride hArgs + theorem NativeStmtPreservesWord_exprStmtCall_stop (name : EvmYul.Identifier) (expected : EvmYul.Literal) @@ -8373,1223 +16730,3135 @@ theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_stop EvmYul.Operation.STOP (by rfl)] exact NativeStmtPreservesWord_exprStmtCall_stop name expected codeOverride -theorem nativeSwitchTempsFreshForNativeBodies_case_matched_not_mem - (switchId tag : Nat) - (body defaultBody : List EvmYul.Yul.Ast.Stmt) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hMem : (tag, body) ∈ cases) : - Backends.nativeSwitchMatchedTempName switchId ∉ - Backends.nativeStmtsWriteNames body := - (hFresh.1 tag body hMem).2 +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_stop + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "stop" [])) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact NativeStmtPreservesWord_exprStmtCall_lowerExprNative_stop name expected _ + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log0 + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "log0" args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [size, offset])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected args _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs) + hShape -theorem nativeSwitchTempsFreshForNativeBodies_case_discr_not_mem - (switchId tag : Nat) - (body defaultBody : List EvmYul.Yul.Ast.Stmt) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hMem : (tag, body) ∈ cases) : - Backends.nativeSwitchDiscrTempName switchId ∉ - Backends.nativeStmtsWriteNames body := - (hFresh.1 tag body hMem).1 +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log1 + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "log1" args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [topic0, size, offset])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected args _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs) + hShape -theorem nativeSwitchTempsFreshForNativeBodies_find_hit_matched_not_mem - (switchId selector tag : Nat) - (body defaultBody : List EvmYul.Yul.Ast.Stmt) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hFind : cases.find? (fun entry => entry.1 == selector) = - some (tag, body)) : - Backends.nativeSwitchMatchedTempName switchId ∉ - Backends.nativeStmtsWriteNames body := by - have hMem : (tag, body) ∈ cases := by - clear hFresh - induction cases with - | nil => - simp [List.find?] at hFind - | cons head rest ih => - cases hHead : (head.1 == selector) - · simp [List.find?, hHead] at hFind - exact List.mem_cons_of_mem head (ih hFind) - · simp [List.find?, hHead] at hFind - simp [hFind] - exact nativeSwitchTempsFreshForNativeBodies_case_matched_not_mem - switchId tag body defaultBody cases hFresh hMem +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log2 + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "log2" args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0 topic1, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [topic1, topic0, size, offset])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected args _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs) + hShape -theorem nativeSwitchTempsFreshForNativeBodies_find_hit_discr_not_mem - (switchId selector tag : Nat) - (body defaultBody : List EvmYul.Yul.Ast.Stmt) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hFind : cases.find? (fun entry => entry.1 == selector) = - some (tag, body)) : - Backends.nativeSwitchDiscrTempName switchId ∉ - Backends.nativeStmtsWriteNames body := by - have hMem : (tag, body) ∈ cases := by - clear hFresh - induction cases with - | nil => - simp [List.find?] at hFind - | cons head rest ih => - cases hHead : (head.1 == selector) - · simp [List.find?, hHead] at hFind - exact List.mem_cons_of_mem head (ih hFind) - · simp [List.find?, hHead] at hFind - simp [hFind] - exact nativeSwitchTempsFreshForNativeBodies_case_discr_not_mem - switchId tag body defaultBody cases hFresh hMem +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log3 + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "log3" args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0 topic1 topic2, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [topic2, topic1, topic0, size, offset])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected args _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs) + hShape -theorem nativeSwitchTempsFreshForNativeBodies_default_matched_not_mem - (switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) : - Backends.nativeSwitchMatchedTempName switchId ∉ - Backends.nativeStmtsWriteNames defaultBody := - hFresh.2.2 +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log4 + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "log4" args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size topic0 topic1 topic2 topic3, + EvmYul.Yul.evalArgs fuel + ((args.map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [topic3, topic2, topic1, topic0, size, offset])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected args _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs) + hShape -theorem nativeSwitchTempsFreshForNativeBodies_default_discr_not_mem - (switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) : - Backends.nativeSwitchDiscrTempName switchId ∉ - Backends.nativeStmtsWriteNames defaultBody := - hFresh.2.1 +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log0_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "log0" args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_nativeEvalArgs_preserves + name expected args _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs) -theorem NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched - (switchId selector tag : Nat) - (body defaultBody : List EvmYul.Yul.Ast.Stmt) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log1_of_nativeEvalArgs + (name : EvmYul.Identifier) (expected : EvmYul.Literal) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hFind : cases.find? (fun entry => entry.1 == selector) = - some (tag, body)) - (hStmtPreserves : - ∀ stmt, stmt ∈ body → - Backends.nativeSwitchMatchedTempName switchId ∉ - Backends.nativeStmtWriteNames stmt → - NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) - expected stmt codeOverride) : - NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) - expected body codeOverride := - NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem - (Backends.nativeSwitchMatchedTempName switchId) expected body codeOverride - (nativeSwitchTempsFreshForNativeBodies_find_hit_matched_not_mem - switchId selector tag body defaultBody cases hFresh hFind) - hStmtPreserves + (reservedNames : List String) + (nextSwitchId : Nat) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "log1" args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_nativeEvalArgs_preserves + name expected args _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs) -theorem NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_discr - (switchId selector tag : Nat) - (body defaultBody : List EvmYul.Yul.Ast.Stmt) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log2_of_nativeEvalArgs + (name : EvmYul.Identifier) (expected : EvmYul.Literal) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hFind : cases.find? (fun entry => entry.1 == selector) = - some (tag, body)) - (hStmtPreserves : - ∀ stmt, stmt ∈ body → - Backends.nativeSwitchDiscrTempName switchId ∉ - Backends.nativeStmtWriteNames stmt → - NativeStmtPreservesWord (Backends.nativeSwitchDiscrTempName switchId) - expected stmt codeOverride) : - NativeBlockPreservesWord (Backends.nativeSwitchDiscrTempName switchId) - expected body codeOverride := - NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem - (Backends.nativeSwitchDiscrTempName switchId) expected body codeOverride - (nativeSwitchTempsFreshForNativeBodies_find_hit_discr_not_mem - switchId selector tag body defaultBody cases hFresh hFind) - hStmtPreserves + (reservedNames : List String) + (nextSwitchId : Nat) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "log2" args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_nativeEvalArgs_preserves + name expected args _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs) -theorem NativeBlockPreservesWord_of_nativeSwitchFresh_default_matched - (switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log3_of_nativeEvalArgs + (name : EvmYul.Identifier) (expected : EvmYul.Literal) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hStmtPreserves : - ∀ stmt, stmt ∈ defaultBody → - Backends.nativeSwitchMatchedTempName switchId ∉ - Backends.nativeStmtWriteNames stmt → - NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) - expected stmt codeOverride) : - NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) - expected defaultBody codeOverride := - NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem - (Backends.nativeSwitchMatchedTempName switchId) expected defaultBody - codeOverride - (nativeSwitchTempsFreshForNativeBodies_default_matched_not_mem - switchId cases defaultBody hFresh) - hStmtPreserves + (reservedNames : List String) + (nextSwitchId : Nat) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "log3" args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_nativeEvalArgs_preserves + name expected args _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs) -theorem NativeBlockPreservesWord_of_nativeSwitchFresh_default_discr - (switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log4_of_nativeEvalArgs + (name : EvmYul.Identifier) (expected : EvmYul.Literal) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hStmtPreserves : - ∀ stmt, stmt ∈ defaultBody → - Backends.nativeSwitchDiscrTempName switchId ∉ - Backends.nativeStmtWriteNames stmt → - NativeStmtPreservesWord (Backends.nativeSwitchDiscrTempName switchId) - expected stmt codeOverride) : - NativeBlockPreservesWord (Backends.nativeSwitchDiscrTempName switchId) - expected defaultBody codeOverride := - NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem - (Backends.nativeSwitchDiscrTempName switchId) expected defaultBody - codeOverride - (nativeSwitchTempsFreshForNativeBodies_default_discr_not_mem - switchId cases defaultBody hFresh) - hStmtPreserves - -@[simp] theorem nativeSwitchCaseIfs_nil - (discrName matchedName : EvmYul.Identifier) : - nativeSwitchCaseIfs discrName matchedName [] = [] := by - rfl + (reservedNames : List String) + (nextSwitchId : Nat) + (args : List YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "log4" args)) = .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_nativeEvalArgs_preserves + name expected args _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected args dispatcher hArgs) -@[simp] theorem nativeSwitchCaseIfs_cons - (discrName matchedName : EvmYul.Identifier) - (entry : Nat × List EvmYul.Yul.Ast.Stmt) - (rest : List (Nat × List EvmYul.Yul.Ast.Stmt)) : - nativeSwitchCaseIfs discrName matchedName (entry :: rest) = - nativeSwitchCaseIf discrName matchedName entry :: - nativeSwitchCaseIfs discrName matchedName rest := by - rfl +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_mstore + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (offsetExpr valExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "mstore" [offsetExpr, valExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset value, + EvmYul.Yul.evalArgs fuel + (([offsetExpr, valExpr].map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [value, offset])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected [offsetExpr, valExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [offsetExpr, valExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hVal)) + hShape + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_mstore_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (offsetExpr valExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "mstore" [offsetExpr, valExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_nativeEvalArgs_preserves + name expected [offsetExpr, valExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [offsetExpr, valExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hVal)) -private theorem list_find?_eq_some_split_false - {α : Type} - (p : α → Bool) : - ∀ {xs : List α} {x : α}, - xs.find? p = some x → - ∃ pre suffix, - xs = pre ++ x :: suffix ∧ - ∀ y, y ∈ pre → p y = false - | [], _, hFind => by - simp [List.find?] at hFind - | y :: ys, x, hFind => by - by_cases hp : p y = true - · have hxy : x = y := by - simpa [List.find?, hp] using hFind.symm - subst x - exact ⟨[], ys, by simp, by simp⟩ - · have hFalse : p y = false := Bool.eq_false_iff.2 hp - have hRest : ys.find? p = some x := by - simpa [List.find?, hFalse] using hFind - rcases list_find?_eq_some_split_false p hRest with - ⟨pre, suffix, hSplit, hPre⟩ - refine ⟨y :: pre, suffix, ?_, ?_⟩ - · simp [hSplit] - · intro z hz - have hz' : z = y ∨ z ∈ pre := by - simpa [List.mem_cons] using hz - rcases hz' with hzy | hzPre - · cases hzy - exact hFalse - · exact hPre z hzPre +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_mstore8 + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (offsetExpr valExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "mstore8" [offsetExpr, valExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset value, + EvmYul.Yul.evalArgs fuel + (([offsetExpr, valExpr].map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [value, offset])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected [offsetExpr, valExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [offsetExpr, valExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hVal)) + hShape + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_mstore8_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (offsetExpr valExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "mstore8" [offsetExpr, valExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_nativeEvalArgs_preserves + name expected [offsetExpr, valExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [offsetExpr, valExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hVal)) -private theorem list_find?_eq_none_all_false - {α : Type} - (p : α → Bool) : - ∀ {xs : List α}, - xs.find? p = none → - ∀ x, x ∈ xs → p x = false - | [], hFind, x, hx => by - simp at hx - | y :: ys, hFind, x, hx => by - by_cases hp : p y = true - · simp [List.find?, hp] at hFind - · have hFalse : p y = false := Bool.eq_false_iff.2 hp - have hRest : ys.find? p = none := by - simpa [List.find?, hFalse] using hFind - have hx' : x = y ∨ x ∈ ys := by - simpa [List.mem_cons] using hx - rcases hx' with hxy | hxTail - · cases hxy - exact hFalse - · exact list_find?_eq_none_all_false p hRest x hxTail +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_sstore + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (slotExpr valExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hSlot : Compiler.Proofs.YulGeneration.Backends.BridgedExpr slotExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "sstore" [slotExpr, valExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState slot value, + EvmYul.Yul.evalArgs fuel + (([slotExpr, valExpr].map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [value, slot])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected [slotExpr, valExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [slotExpr, valExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hSlot + · exact hVal)) + hShape + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_sstore_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (slotExpr valExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hSlot : Compiler.Proofs.YulGeneration.Backends.BridgedExpr slotExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "sstore" [slotExpr, valExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_nativeEvalArgs_preserves + name expected [slotExpr, valExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [slotExpr, valExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hSlot + · exact hVal)) -private theorem uint256_ofNat_ne_of_ne_of_lt - {a b : Nat} - (ha : a < EvmYul.UInt256.size) - (hb : b < EvmYul.UInt256.size) - (hne : a ≠ b) : - EvmYul.UInt256.ofNat a ≠ EvmYul.UInt256.ofNat b := by - intro h - apply hne - have hToNat := congrArg EvmYul.UInt256.toNat h - rw [uint256_ofNat_toNat_of_lt a ha, - uint256_ofNat_toNat_of_lt b hb] at hToNat - exact hToNat +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_tstore + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (slotExpr valExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hSlot : Compiler.Proofs.YulGeneration.Backends.BridgedExpr slotExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "tstore" [slotExpr, valExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState slot value, + EvmYul.Yul.evalArgs fuel + (([slotExpr, valExpr].map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [value, slot])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected [slotExpr, valExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [slotExpr, valExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hSlot + · exact hVal)) + hShape + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_tstore_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (slotExpr valExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hSlot : Compiler.Proofs.YulGeneration.Backends.BridgedExpr slotExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "tstore" [slotExpr, valExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_nativeEvalArgs_preserves + name expected [slotExpr, valExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [slotExpr, valExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hSlot + · exact hVal)) -private theorem nativeSwitch_prefix_miss_of_selector_find - (selector : Nat) - (cases pre suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) - (state : EvmYul.Yul.State) - (discrName : EvmYul.Identifier) - (hCases : cases = pre ++ (tag, body) :: suffix) - (hPrefix : - ∀ entry, entry ∈ pre → (fun entry : Nat × List EvmYul.Yul.Ast.Stmt => - entry.1 == selector) entry = false) - (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) : - ∀ tag' body', (tag', body') ∈ pre → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := by - intro tag' body' hmem hDiscrTag - have hPrefixFalse := hPrefix (tag', body') hmem - have hTagNe : tag' ≠ selector := by - intro hEq - have hTrue : (tag' == selector) = true := beq_iff_eq.mpr hEq - have hFalse : (tag' == selector) = false := by - simpa using hPrefixFalse - rw [hTrue] at hFalse - contradiction - have hCaseMem : (tag', body') ∈ cases := by - rw [hCases] - simp [hmem] - have hWordNe : - EvmYul.UInt256.ofNat selector ≠ EvmYul.UInt256.ofNat tag' := - uint256_ofNat_ne_of_ne_of_lt hSelectorRange - (hTagsRange tag' body' hCaseMem) (Ne.symm hTagNe) - exact hWordNe (hDiscrSelector.symm.trans hDiscrTag) +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_return + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (offsetExpr sizeExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "return" [offsetExpr, sizeExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size, + EvmYul.Yul.evalArgs fuel + (([offsetExpr, sizeExpr].map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [size, offset])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected [offsetExpr, sizeExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [offsetExpr, sizeExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hSize)) + hShape + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_return_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (offsetExpr sizeExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "return" [offsetExpr, sizeExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_nativeEvalArgs_preserves + name expected [offsetExpr, sizeExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [offsetExpr, sizeExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hSize)) -/-- A selector lookup hit exposes the generated case list as a miss prefix, - selected case, and suffix. This is the list-shape bridge consumed by the - native lazy-switch execution lemmas. -/ -theorem nativeSwitch_find_hit_split - (selector : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) - (hFind : - cases.find? (fun entry => entry.1 == selector) = some (tag, body)) : - ∃ pre suffix, - cases = pre ++ (tag, body) :: suffix ∧ - tag = selector ∧ - ∀ entry, entry ∈ pre → - (fun entry : Nat × List EvmYul.Yul.Ast.Stmt => - entry.1 == selector) entry = false := by - rcases list_find?_eq_some_split_false - (fun entry : Nat × List EvmYul.Yul.Ast.Stmt => entry.1 == selector) - hFind with - ⟨pre, suffix, hSplit, hPrefix⟩ - have hSelected : - (fun entry : Nat × List EvmYul.Yul.Ast.Stmt => - entry.1 == selector) (tag, body) = true := - List.find?_some - (p := fun entry : Nat × List EvmYul.Yul.Ast.Stmt => - entry.1 == selector) hFind - have hTag : tag = selector := by - exact beq_iff_eq.mp hSelected - exact ⟨pre, suffix, hSplit, hTag, hPrefix⟩ +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_revert + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (offsetExpr sizeExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "revert" [offsetExpr, sizeExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState offset size, + EvmYul.Yul.evalArgs fuel + (([offsetExpr, sizeExpr].map Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [size, offset])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected [offsetExpr, sizeExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [offsetExpr, sizeExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hSize)) + hShape + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_revert_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (offsetExpr sizeExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "revert" [offsetExpr, sizeExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_nativeEvalArgs_preserves + name expected [offsetExpr, sizeExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [offsetExpr, sizeExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hSize)) -/-- A selector lookup miss proves every generated case tag misses the native - dispatcher discriminator when the discriminator contains that selector and - all case tags are in the `UInt256` range. -/ -theorem nativeSwitch_find_none_all_miss - (selector : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (state : EvmYul.Yul.State) - (discrName : EvmYul.Identifier) - (hFind : - cases.find? (fun entry => entry.1 == selector) = none) - (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : - ∀ tag body, (tag, body) ∈ cases → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag := by - intro tag body hmem hDiscrTag - have hFalse := - list_find?_eq_none_all_false - (fun entry : Nat × List EvmYul.Yul.Ast.Stmt => entry.1 == selector) - hFind (tag, body) hmem - have hTagNe : tag ≠ selector := by - intro hEq - have hTrue : (tag == selector) = true := beq_iff_eq.mpr hEq - have hFalse' : (tag == selector) = false := by - simpa using hFalse - rw [hTrue] at hFalse' - contradiction - have hWordNe : - EvmYul.UInt256.ofNat selector ≠ EvmYul.UInt256.ofNat tag := - uint256_ofNat_ne_of_ne_of_lt hSelectorRange - (hTagsRange tag body hmem) (Ne.symm hTagNe) - exact hWordNe (hDiscrSelector.symm.trans hDiscrTag) +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_calldatacopy + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (destOffset sourceOffset sizeExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hDest : Compiler.Proofs.YulGeneration.Backends.BridgedExpr destOffset) + (hSource : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sourceOffset) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "calldatacopy" [destOffset, sourceOffset, sizeExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState mstart datastart size, + EvmYul.Yul.evalArgs fuel + (([destOffset, sourceOffset, sizeExpr].map + Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [size, datastart, mstart])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected [destOffset, sourceOffset, sizeExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [destOffset, sourceOffset, sizeExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl | rfl + · exact hDest + · exact hSource + · exact hSize)) + hShape + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_returndatacopy + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (destOffset sourceOffset sizeExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hDest : Compiler.Proofs.YulGeneration.Backends.BridgedExpr destOffset) + (hSource : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sourceOffset) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "returndatacopy" [destOffset, sourceOffset, sizeExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hShape : + ∀ fuel state, + state[name]! = expected → + ∃ argState mstart rstart size, + EvmYul.Yul.evalArgs fuel + (([destOffset, sourceOffset, sizeExpr].map + Backends.lowerExprNative).reverse) + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + state = + .ok (argState, [size, rstart, mstart])) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves + name expected [destOffset, sourceOffset, sizeExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [destOffset, sourceOffset, sizeExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl | rfl + · exact hDest + · exact hSource + · exact hSize)) + hShape + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_calldatacopy_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (destOffset sourceOffset sizeExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hDest : Compiler.Proofs.YulGeneration.Backends.BridgedExpr destOffset) + (hSource : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sourceOffset) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "calldatacopy" [destOffset, sourceOffset, sizeExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_nativeEvalArgs_preserves + name expected [destOffset, sourceOffset, sizeExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [destOffset, sourceOffset, sizeExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl | rfl + · exact hDest + · exact hSource + · exact hSize)) + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_returndatacopy_of_nativeEvalArgs + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (destOffset sourceOffset sizeExpr : YulExpr) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hDest : Compiler.Proofs.YulGeneration.Backends.BridgedExpr destOffset) + (hSource : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sourceOffset) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId + (.expr (.call "returndatacopy" [destOffset, sourceOffset, sizeExpr])) = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_nativeEvalArgs_preserves + name expected [destOffset, sourceOffset, sizeExpr] _ + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + name expected [destOffset, sourceOffset, sizeExpr] dispatcher + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl | rfl + · exact hDest + · exact hSource + · exact hSize)) + +inductive NativePreservableStraightStmt : YulStmt → Prop + | comment (text : String) : + NativePreservableStraightStmt (.comment text) + | let_ (target : EvmYul.Identifier) (value : YulExpr) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) : + NativePreservableStraightStmt (.let_ target value) + | letMany (targets : List EvmYul.Identifier) (value : YulExpr) + (hTargets : targets ≠ []) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) : + NativePreservableStraightStmt (.letMany targets value) + | assign (target : EvmYul.Identifier) (value : YulExpr) + (hValue : Compiler.Proofs.YulGeneration.Backends.BridgedExpr value) : + NativePreservableStraightStmt (.assign target value) + | expr_call (func : EvmYul.Identifier) (args : List YulExpr) + (hName : Compiler.Proofs.YulGeneration.Backends.allowedExprCallName func) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) : + NativePreservableStraightStmt (.expr (.call func args)) + | expr_sstore (slotExpr valExpr : YulExpr) + (hSlot : Compiler.Proofs.YulGeneration.Backends.BridgedExpr slotExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) : + NativePreservableStraightStmt (.expr (.call "sstore" [slotExpr, valExpr])) + | expr_tstore (slotExpr valExpr : YulExpr) + (hSlot : Compiler.Proofs.YulGeneration.Backends.BridgedExpr slotExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) : + NativePreservableStraightStmt (.expr (.call "tstore" [slotExpr, valExpr])) + | expr_mstore (offsetExpr valExpr : YulExpr) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) : + NativePreservableStraightStmt (.expr (.call "mstore" [offsetExpr, valExpr])) + | expr_mstore8 (offsetExpr valExpr : YulExpr) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hVal : Compiler.Proofs.YulGeneration.Backends.BridgedExpr valExpr) : + NativePreservableStraightStmt (.expr (.call "mstore8" [offsetExpr, valExpr])) + | expr_stop : + NativePreservableStraightStmt (.expr (.call "stop" [])) + | expr_return (offsetExpr sizeExpr : YulExpr) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) : + NativePreservableStraightStmt + (.expr (.call "return" [offsetExpr, sizeExpr])) + | expr_revert (offsetExpr sizeExpr : YulExpr) + (hOffset : Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) : + NativePreservableStraightStmt + (.expr (.call "revert" [offsetExpr, sizeExpr])) + | expr_log0 (args : List YulExpr) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) : + NativePreservableStraightStmt (.expr (.call "log0" args)) + | expr_log1 (args : List YulExpr) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) : + NativePreservableStraightStmt (.expr (.call "log1" args)) + | expr_log2 (args : List YulExpr) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) : + NativePreservableStraightStmt (.expr (.call "log2" args)) + | expr_log3 (args : List YulExpr) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) : + NativePreservableStraightStmt (.expr (.call "log3" args)) + | expr_log4 (args : List YulExpr) + (hArgs : + ∀ arg, arg ∈ args → + Compiler.Proofs.YulGeneration.Backends.BridgedExpr arg) : + NativePreservableStraightStmt (.expr (.call "log4" args)) + | expr_calldatacopy (destOffset sourceOffset sizeExpr : YulExpr) + (hDest : Compiler.Proofs.YulGeneration.Backends.BridgedExpr destOffset) + (hSource : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sourceOffset) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) : + NativePreservableStraightStmt + (.expr (.call "calldatacopy" [destOffset, sourceOffset, sizeExpr])) + | expr_returndatacopy (destOffset sourceOffset sizeExpr : YulExpr) + (hDest : Compiler.Proofs.YulGeneration.Backends.BridgedExpr destOffset) + (hSource : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sourceOffset) + (hSize : Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr) : + NativePreservableStraightStmt + (.expr (.call "returndatacopy" [destOffset, sourceOffset, sizeExpr])) + +/-- Mapping-free straight statements whose lowered native form preserves a +marker word for the actual runtime contract. + +This is intentionally parallel to `NativePreservableStraightStmt`, but every +expression premise is recursive `NativeMappingFreeBridgedExpr`. The mapping +helper path remains covered by `NativePreservableStraightStmt`; this fragment is +for no-mapping/generated bodies that should not require the synthetic +`mappingSlot` contract. -/ +inductive NativeMappingFreePreservableStraightStmt : YulStmt → Prop + | comment (text : String) : + NativeMappingFreePreservableStraightStmt (.comment text) + | let_ (target : EvmYul.Identifier) (value : YulExpr) + (hValue : NativeMappingFreeBridgedExpr value) : + NativeMappingFreePreservableStraightStmt (.let_ target value) + | letMany (targets : List EvmYul.Identifier) (value : YulExpr) + (hTargets : targets ≠ []) + (hValue : NativeMappingFreeBridgedExpr value) : + NativeMappingFreePreservableStraightStmt (.letMany targets value) + | assign (target : EvmYul.Identifier) (value : YulExpr) + (hValue : NativeMappingFreeBridgedExpr value) : + NativeMappingFreePreservableStraightStmt (.assign target value) + | expr_call (func : EvmYul.Identifier) (args : List YulExpr) + (hName : Compiler.Proofs.YulGeneration.Backends.allowedExprCallName func) + (hNoMapping : func ≠ "mappingSlot") + (hArgs : ∀ arg, arg ∈ args → NativeMappingFreeBridgedExpr arg) : + NativeMappingFreePreservableStraightStmt (.expr (.call func args)) + | expr_sstore (slotExpr valExpr : YulExpr) + (hSlot : NativeMappingFreeBridgedExpr slotExpr) + (hVal : NativeMappingFreeBridgedExpr valExpr) : + NativeMappingFreePreservableStraightStmt + (.expr (.call "sstore" [slotExpr, valExpr])) + | expr_tstore (slotExpr valExpr : YulExpr) + (hSlot : NativeMappingFreeBridgedExpr slotExpr) + (hVal : NativeMappingFreeBridgedExpr valExpr) : + NativeMappingFreePreservableStraightStmt + (.expr (.call "tstore" [slotExpr, valExpr])) + | expr_mstore (offsetExpr valExpr : YulExpr) + (hOffset : NativeMappingFreeBridgedExpr offsetExpr) + (hVal : NativeMappingFreeBridgedExpr valExpr) : + NativeMappingFreePreservableStraightStmt + (.expr (.call "mstore" [offsetExpr, valExpr])) + | expr_mstore8 (offsetExpr valExpr : YulExpr) + (hOffset : NativeMappingFreeBridgedExpr offsetExpr) + (hVal : NativeMappingFreeBridgedExpr valExpr) : + NativeMappingFreePreservableStraightStmt + (.expr (.call "mstore8" [offsetExpr, valExpr])) + | expr_stop : + NativeMappingFreePreservableStraightStmt (.expr (.call "stop" [])) + | expr_return (offsetExpr sizeExpr : YulExpr) + (hOffset : NativeMappingFreeBridgedExpr offsetExpr) + (hSize : NativeMappingFreeBridgedExpr sizeExpr) : + NativeMappingFreePreservableStraightStmt + (.expr (.call "return" [offsetExpr, sizeExpr])) + | expr_revert (offsetExpr sizeExpr : YulExpr) + (hOffset : NativeMappingFreeBridgedExpr offsetExpr) + (hSize : NativeMappingFreeBridgedExpr sizeExpr) : + NativeMappingFreePreservableStraightStmt + (.expr (.call "revert" [offsetExpr, sizeExpr])) + | expr_log0 (args : List YulExpr) + (hArgs : ∀ arg, arg ∈ args → NativeMappingFreeBridgedExpr arg) : + NativeMappingFreePreservableStraightStmt (.expr (.call "log0" args)) + | expr_log1 (args : List YulExpr) + (hArgs : ∀ arg, arg ∈ args → NativeMappingFreeBridgedExpr arg) : + NativeMappingFreePreservableStraightStmt (.expr (.call "log1" args)) + | expr_log2 (args : List YulExpr) + (hArgs : ∀ arg, arg ∈ args → NativeMappingFreeBridgedExpr arg) : + NativeMappingFreePreservableStraightStmt (.expr (.call "log2" args)) + | expr_log3 (args : List YulExpr) + (hArgs : ∀ arg, arg ∈ args → NativeMappingFreeBridgedExpr arg) : + NativeMappingFreePreservableStraightStmt (.expr (.call "log3" args)) + | expr_log4 (args : List YulExpr) + (hArgs : ∀ arg, arg ∈ args → NativeMappingFreeBridgedExpr arg) : + NativeMappingFreePreservableStraightStmt (.expr (.call "log4" args)) + | expr_calldatacopy (destOffset sourceOffset sizeExpr : YulExpr) + (hDest : NativeMappingFreeBridgedExpr destOffset) + (hSource : NativeMappingFreeBridgedExpr sourceOffset) + (hSize : NativeMappingFreeBridgedExpr sizeExpr) : + NativeMappingFreePreservableStraightStmt + (.expr (.call "calldatacopy" [destOffset, sourceOffset, sizeExpr])) + | expr_returndatacopy (destOffset sourceOffset sizeExpr : YulExpr) + (hDest : NativeMappingFreeBridgedExpr destOffset) + (hSource : NativeMappingFreeBridgedExpr sourceOffset) + (hSize : NativeMappingFreeBridgedExpr sizeExpr) : + NativeMappingFreePreservableStraightStmt + (.expr (.call "returndatacopy" [destOffset, sourceOffset, sizeExpr])) + +def NativeMappingFreePreservableStraightStmts (stmts : List YulStmt) : Prop := + ∀ stmt, stmt ∈ stmts → NativeMappingFreePreservableStraightStmt stmt + +/-- Extra facts needed to translate a historical `BridgedExpr` witness into +the mapping-free native fragment. The historical predicate admits the +`mappingSlot` helper; the actual-runtime preservation path excludes it +recursively. -/ +def NativeMappingFreeSideConditionForBridgedExpr : YulExpr → Prop + | .call "mappingSlot" _ => False + | .call _ args => + ∀ arg, arg ∈ args → NativeMappingFreeSideConditionForBridgedExpr arg + | _ => True + +theorem NativeMappingFreeBridgedExpr.of_bridgedExpr + {expr : YulExpr} + (hExpr : Compiler.Proofs.YulGeneration.Backends.BridgedExpr expr) + (hSide : NativeMappingFreeSideConditionForBridgedExpr expr) : + NativeMappingFreeBridgedExpr expr := by + induction hExpr with + | lit n => + exact NativeMappingFreeBridgedExpr.lit n + | hex n => + exact NativeMappingFreeBridgedExpr.hex n + | str s => + exact NativeMappingFreeBridgedExpr.str s + | ident name => + exact NativeMappingFreeBridgedExpr.ident name + | call func args hName hArgs ih => + have hNoMapping : func ≠ "mappingSlot" := by + intro hFunc + subst func + simp [NativeMappingFreeSideConditionForBridgedExpr] at hSide + have hArgsSide : + ∀ arg, arg ∈ args → + NativeMappingFreeSideConditionForBridgedExpr arg := by + simpa [NativeMappingFreeSideConditionForBridgedExpr, hNoMapping] using + hSide + exact + NativeMappingFreeBridgedExpr.call func args hName hNoMapping + (by + intro arg hArg + exact ih arg hArg (hArgsSide arg hArg)) + +/-- Extra facts needed to view a historical `BridgedStraightStmt` as a +mapping-free native matched-flag-preservable straight statement. + +The side condition excludes the mapping helper and other non-straight +function-body forms while making the few historical gaps explicit (`letMany` +values and `revert` arguments). -/ +def NativeMappingFreeSideConditionForBridgedStraightStmt : + YulStmt → Prop + | .let_ _ value => + NativeMappingFreeSideConditionForBridgedExpr value + | .letMany targets value => + targets ≠ [] ∧ NativeMappingFreeBridgedExpr value + | .assign _ value => + NativeMappingFreeSideConditionForBridgedExpr value + | .expr (.call "sstore" [.call "mappingSlot" _, _]) => False + | .expr (.call "sstore" [.lit _, valExpr]) => + NativeMappingFreeSideConditionForBridgedExpr valExpr + | .expr (.call "sstore" [.ident _, valExpr]) => + NativeMappingFreeSideConditionForBridgedExpr valExpr + | .expr (.call "sstore" [.call "add" [leftExpr, rightExpr], valExpr]) => + NativeMappingFreeSideConditionForBridgedExpr leftExpr ∧ + NativeMappingFreeSideConditionForBridgedExpr rightExpr ∧ + NativeMappingFreeSideConditionForBridgedExpr valExpr + | .expr (.call "mstore" [offsetExpr, valExpr]) => + NativeMappingFreeSideConditionForBridgedExpr offsetExpr ∧ + NativeMappingFreeSideConditionForBridgedExpr valExpr + | .expr (.call "tstore" [offsetExpr, valExpr]) => + NativeMappingFreeSideConditionForBridgedExpr offsetExpr ∧ + NativeMappingFreeSideConditionForBridgedExpr valExpr + | .expr (.call "return" [offsetExpr, sizeExpr]) => + NativeMappingFreeSideConditionForBridgedExpr offsetExpr ∧ + NativeMappingFreeSideConditionForBridgedExpr sizeExpr + | .expr (.call "revert" [offsetExpr, sizeExpr]) => + NativeMappingFreeBridgedExpr offsetExpr ∧ + NativeMappingFreeBridgedExpr sizeExpr + | .expr (.call func args) => + Compiler.Proofs.YulGeneration.isYulLogName func = true → + ∀ arg, arg ∈ args → NativeMappingFreeSideConditionForBridgedExpr arg + | .«leave» => False + | .funcDef _ _ _ _ => False + | _ => True + +/-- Translate the older straight bridged predicate into the no-mapping native +matched-flag-preservation fragment. + +This lets generated no-mapping bodies reuse `BridgedStraightStmts` closure +proofs while still targeting the actual lowered runtime contract rather than a +synthetic mapping-helper contract. -/ +theorem NativeMappingFreePreservableStraightStmt.of_bridgedStraightStmt + {stmt : YulStmt} + (hStmt : + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmt stmt) + (hSide : + NativeMappingFreeSideConditionForBridgedStraightStmt stmt) : + NativeMappingFreePreservableStraightStmt stmt := by + cases hStmt with + | comment text => + exact NativeMappingFreePreservableStraightStmt.comment text + | let_ name value hValue => + exact + NativeMappingFreePreservableStraightStmt.let_ name value + (NativeMappingFreeBridgedExpr.of_bridgedExpr hValue hSide) + | letMany names value => + exact + NativeMappingFreePreservableStraightStmt.letMany names value + hSide.1 hSide.2 + | assign name value hValue => + exact + NativeMappingFreePreservableStraightStmt.assign name value + (NativeMappingFreeBridgedExpr.of_bridgedExpr hValue hSide) + | «leave» => + cases hSide + | expr_sstore_mapping baseExpr keyExpr valExpr hBase hKey hVal => + cases hSide + | expr_sstore_lit slot valExpr hVal => + exact + NativeMappingFreePreservableStraightStmt.expr_sstore (.lit slot) valExpr + (NativeMappingFreeBridgedExpr.lit slot) + (NativeMappingFreeBridgedExpr.of_bridgedExpr hVal hSide) + | expr_sstore_ident slotName valExpr hVal => + exact + NativeMappingFreePreservableStraightStmt.expr_sstore (.ident slotName) + valExpr (NativeMappingFreeBridgedExpr.ident slotName) + (NativeMappingFreeBridgedExpr.of_bridgedExpr hVal hSide) + | expr_sstore_add leftExpr rightExpr valExpr hLeft hRight hVal => + exact + NativeMappingFreePreservableStraightStmt.expr_sstore + (.call "add" [leftExpr, rightExpr]) valExpr + (NativeMappingFreeBridgedExpr.call "add" [leftExpr, rightExpr] + (by + left + simp [Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins]) + (by decide) + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact + NativeMappingFreeBridgedExpr.of_bridgedExpr hLeft hSide.1 + · exact + NativeMappingFreeBridgedExpr.of_bridgedExpr hRight hSide.2.1)) + (NativeMappingFreeBridgedExpr.of_bridgedExpr hVal hSide.2.2) + | expr_mstore offsetExpr valExpr hOffset hVal => + exact + NativeMappingFreePreservableStraightStmt.expr_mstore offsetExpr valExpr + (NativeMappingFreeBridgedExpr.of_bridgedExpr hOffset hSide.1) + (NativeMappingFreeBridgedExpr.of_bridgedExpr hVal hSide.2) + | expr_tstore offsetExpr valExpr hOffset hVal => + exact + NativeMappingFreePreservableStraightStmt.expr_tstore offsetExpr valExpr + (NativeMappingFreeBridgedExpr.of_bridgedExpr hOffset hSide.1) + (NativeMappingFreeBridgedExpr.of_bridgedExpr hVal hSide.2) + | expr_stop => + exact NativeMappingFreePreservableStraightStmt.expr_stop + | expr_return offsetExpr sizeExpr hOffset hSize => + exact + NativeMappingFreePreservableStraightStmt.expr_return offsetExpr sizeExpr + (NativeMappingFreeBridgedExpr.of_bridgedExpr hOffset hSide.1) + (NativeMappingFreeBridgedExpr.of_bridgedExpr hSize hSide.2) + | expr_revert offsetExpr sizeExpr => + exact + NativeMappingFreePreservableStraightStmt.expr_revert offsetExpr sizeExpr + hSide.1 hSide.2 + | expr_log func args hLog hArgs => + have hFunc : + func = "log0" ∨ func = "log1" ∨ func = "log2" ∨ + func = "log3" ∨ func = "log4" := by + simp [Compiler.Proofs.YulGeneration.isYulLogName] at hLog + tauto + rcases hFunc with rfl | rfl | rfl | rfl | rfl + · refine NativeMappingFreePreservableStraightStmt.expr_log0 args ?_ + have hArgsSide : + ∀ arg, arg ∈ args → + NativeMappingFreeSideConditionForBridgedExpr arg := by + simpa [NativeMappingFreeSideConditionForBridgedStraightStmt] using + (hSide (by simp [Compiler.Proofs.YulGeneration.isYulLogName])) + intro arg hArg + exact + NativeMappingFreeBridgedExpr.of_bridgedExpr (hArgs arg hArg) + (hArgsSide arg hArg) + · refine NativeMappingFreePreservableStraightStmt.expr_log1 args ?_ + have hArgsSide : + ∀ arg, arg ∈ args → + NativeMappingFreeSideConditionForBridgedExpr arg := by + simpa [NativeMappingFreeSideConditionForBridgedStraightStmt] using + (hSide (by simp [Compiler.Proofs.YulGeneration.isYulLogName])) + intro arg hArg + exact + NativeMappingFreeBridgedExpr.of_bridgedExpr (hArgs arg hArg) + (hArgsSide arg hArg) + · refine NativeMappingFreePreservableStraightStmt.expr_log2 args ?_ + have hArgsSide : + ∀ arg, arg ∈ args → + NativeMappingFreeSideConditionForBridgedExpr arg := by + simpa [NativeMappingFreeSideConditionForBridgedStraightStmt] using + (hSide (by simp [Compiler.Proofs.YulGeneration.isYulLogName])) + intro arg hArg + exact + NativeMappingFreeBridgedExpr.of_bridgedExpr (hArgs arg hArg) + (hArgsSide arg hArg) + · refine NativeMappingFreePreservableStraightStmt.expr_log3 args ?_ + have hArgsSide : + ∀ arg, arg ∈ args → + NativeMappingFreeSideConditionForBridgedExpr arg := by + simpa [NativeMappingFreeSideConditionForBridgedStraightStmt] using + (hSide (by simp [Compiler.Proofs.YulGeneration.isYulLogName])) + intro arg hArg + exact + NativeMappingFreeBridgedExpr.of_bridgedExpr (hArgs arg hArg) + (hArgsSide arg hArg) + · refine NativeMappingFreePreservableStraightStmt.expr_log4 args ?_ + have hArgsSide : + ∀ arg, arg ∈ args → + NativeMappingFreeSideConditionForBridgedExpr arg := by + simpa [NativeMappingFreeSideConditionForBridgedStraightStmt] using + (hSide (by simp [Compiler.Proofs.YulGeneration.isYulLogName])) + intro arg hArg + exact + NativeMappingFreeBridgedExpr.of_bridgedExpr (hArgs arg hArg) + (hArgsSide arg hArg) + | funcDef name params rets body => + cases hSide + +theorem NativeMappingFreePreservableStraightStmts.of_bridgedStraightStmts + {stmts : List YulStmt} + (hStmts : + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts stmts) + (hSide : + ∀ stmt, stmt ∈ stmts → + NativeMappingFreeSideConditionForBridgedStraightStmt stmt) : + NativeMappingFreePreservableStraightStmts stmts := by + intro stmt hMem + exact + NativeMappingFreePreservableStraightStmt.of_bridgedStraightStmt + (hStmts stmt hMem) (hSide stmt hMem) -/-- If no case tag matches and the matched flag is still clear, the generated - native switch case chain skips every case body and leaves the state - unchanged. -/ -theorem exec_nativeSwitchCaseIfs_all_miss_fuel - (fuel : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) +/-- Extra facts needed to view a historical `BridgedStraightStmt` as a native +matched-flag-preservable straight statement. + +Most bridged-straight constructors already carry exactly the data needed by +`NativePreservableStraightStmt`. The exceptions are explicit here: `letMany` +needs a nonempty target list and a bridged value, `revert` needs bridged +arguments, and `leave`/`funcDef` are outside this native preservation fragment. +-/ +def NativePreservableSideConditionForBridgedStraightStmt : + YulStmt → Prop + | .letMany targets value => + targets ≠ [] ∧ + Compiler.Proofs.YulGeneration.Backends.BridgedExpr value + | .expr (.call "revert" [offsetExpr, sizeExpr]) => + Compiler.Proofs.YulGeneration.Backends.BridgedExpr offsetExpr ∧ + Compiler.Proofs.YulGeneration.Backends.BridgedExpr sizeExpr + | .«leave» => False + | .funcDef _ _ _ _ => False + | _ => True + +private theorem bridgedExpr_mappingSlot_of_bridged + (baseExpr keyExpr : YulExpr) + (hBase : Compiler.Proofs.YulGeneration.Backends.BridgedExpr baseExpr) + (hKey : Compiler.Proofs.YulGeneration.Backends.BridgedExpr keyExpr) : + Compiler.Proofs.YulGeneration.Backends.BridgedExpr + (.call "mappingSlot" [baseExpr, keyExpr]) := by + exact + Compiler.Proofs.YulGeneration.Backends.BridgedExpr.call "mappingSlot" + [baseExpr, keyExpr] + (by + left + simp [Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins]) + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hBase + · exact hKey) + +/-- Translate the older straight bridged predicate into the native +matched-flag-preservation fragment, making the few missing side conditions +explicit. + +This is a reusable bridge for selector-hit success: once generated bodies are +shown to compile into the straight bridged fragment with these side conditions, +the native harness can derive per-statement matched-flag preservation without +the dispatcher proof carrying an ad hoc predicate conversion. -/ +theorem NativePreservableStraightStmt.of_bridgedStraightStmt + {stmt : YulStmt} + (hStmt : + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmt stmt) + (hSide : + NativePreservableSideConditionForBridgedStraightStmt stmt) : + NativePreservableStraightStmt stmt := by + cases hStmt with + | comment text => + exact NativePreservableStraightStmt.comment text + | let_ name value hValue => + exact NativePreservableStraightStmt.let_ name value hValue + | letMany names value => + exact NativePreservableStraightStmt.letMany names value hSide.1 hSide.2 + | assign name value hValue => + exact NativePreservableStraightStmt.assign name value hValue + | «leave» => + cases hSide + | expr_sstore_mapping baseExpr keyExpr valExpr hBase hKey hVal => + exact + NativePreservableStraightStmt.expr_sstore + (.call "mappingSlot" [baseExpr, keyExpr]) valExpr + (bridgedExpr_mappingSlot_of_bridged baseExpr keyExpr hBase hKey) + hVal + | expr_sstore_lit slot valExpr hVal => + exact + NativePreservableStraightStmt.expr_sstore (.lit slot) valExpr + (Compiler.Proofs.YulGeneration.Backends.BridgedExpr.lit slot) hVal + | expr_sstore_ident slotName valExpr hVal => + exact + NativePreservableStraightStmt.expr_sstore (.ident slotName) valExpr + (Compiler.Proofs.YulGeneration.Backends.BridgedExpr.ident slotName) + hVal + | expr_sstore_add leftExpr rightExpr valExpr hLeft hRight hVal => + exact + NativePreservableStraightStmt.expr_sstore + (.call "add" [leftExpr, rightExpr]) valExpr + (Compiler.Proofs.YulGeneration.Backends.BridgedExpr.call "add" + [leftExpr, rightExpr] + (by + left + simp [Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins]) + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hLeft + · exact hRight)) + hVal + | expr_mstore offsetExpr valExpr hOffset hVal => + exact NativePreservableStraightStmt.expr_mstore offsetExpr valExpr hOffset hVal + | expr_tstore offsetExpr valExpr hOffset hVal => + exact NativePreservableStraightStmt.expr_tstore offsetExpr valExpr hOffset hVal + | expr_stop => + exact NativePreservableStraightStmt.expr_stop + | expr_return offsetExpr sizeExpr hOffset hSize => + exact NativePreservableStraightStmt.expr_return offsetExpr sizeExpr hOffset hSize + | expr_revert offsetExpr sizeExpr => + exact NativePreservableStraightStmt.expr_revert offsetExpr sizeExpr hSide.1 hSide.2 + | expr_log func args hLog hArgs => + have hFunc : + func = "log0" ∨ func = "log1" ∨ func = "log2" ∨ + func = "log3" ∨ func = "log4" := by + simp [Compiler.Proofs.YulGeneration.isYulLogName] at hLog + tauto + rcases hFunc with rfl | rfl | rfl | rfl | rfl + · exact NativePreservableStraightStmt.expr_log0 args hArgs + · exact NativePreservableStraightStmt.expr_log1 args hArgs + · exact NativePreservableStraightStmt.expr_log2 args hArgs + · exact NativePreservableStraightStmt.expr_log3 args hArgs + · exact NativePreservableStraightStmt.expr_log4 args hArgs + | funcDef name params rets body => + cases hSide + +def NativePreservableStraightStmts (stmts : List YulStmt) : Prop := + ∀ stmt, stmt ∈ stmts → NativePreservableStraightStmt stmt + +theorem NativePreservableStraightStmts.of_bridgedStraightStmts + {stmts : List YulStmt} + (hStmts : + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts stmts) + (hSide : + ∀ stmt, stmt ∈ stmts → + NativePreservableSideConditionForBridgedStraightStmt stmt) : + NativePreservableStraightStmts stmts := by + intro stmt hMem + exact + NativePreservableStraightStmt.of_bridgedStraightStmt + (hStmts stmt hMem) (hSide stmt hMem) + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_of_mappingFreePreservableStraightStmt + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (stmt : YulStmt) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (nativeStmt : EvmYul.Yul.Ast.Stmt) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hMiss : - ∀ tag body, (tag, body) ∈ cases → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag) : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .ok state := by - induction cases generalizing fuel codeOverride state discrName matchedName with + (hStmt : NativeMappingFreePreservableStraightStmt stmt) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId stmt = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hFresh : name ∉ Backends.nativeStmtWriteNames nativeStmt) : + NativeStmtPreservesWord name expected nativeStmt codeOverride := by + induction hStmt with + | comment text => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_comment] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact NativeStmtPreservesWord_empty_block name expected codeOverride + | let_ target value hValue => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_let] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_let_lowerExprNative_of_mappingFreeBridgedExpr + name expected target value codeOverride + (nativeStmtWriteNames_let_singleton_not_mem_ne name target + (some (Backends.lowerExprNative value)) hFresh) + hValue + | letMany targets value hTargets hValue => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_letMany] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_letMany_lowerExprNative_of_mappingFreeBridgedExpr + name expected targets value codeOverride hTargets + (nativeStmtWriteNames_let_not_mem_vars name targets + (some (Backends.lowerExprNative value)) hFresh) + hValue + | assign target value hValue => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_assign] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_lowerAssignNative_of_mappingFreeBridgedExpr + name expected target value codeOverride + (nativeStmtWriteNames_lowerAssignNative_not_mem_ne name target value + hFresh) + hValue + | expr_call func args hName hNoMapping hArgs => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + have hNativeArgs : + NativeEvalArgsPreservesWord name expected + ((args.map Backends.lowerExprNative).reverse) codeOverride := + NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected args codeOverride hArgs + cases hOp : Backends.lookupRuntimePrimOp func with + | some op => + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + name func expected args op codeOverride hOp hNativeArgs + (NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp + name func expected op hName hOp) + | none => + exfalso + unfold Backends.lookupRuntimePrimOp at hOp + split at hOp <;> simp at hOp + simp [Compiler.Proofs.YulGeneration.Backends.allowedExprCallName, + Compiler.Proofs.YulGeneration.Backends.bridgedBuiltins, + hNoMapping] at hName + tauto + | expr_sstore slotExpr valExpr hSlot hVal => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_nativeEvalArgs_preserves + name expected [slotExpr, valExpr] codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected [slotExpr, valExpr] codeOverride + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hSlot + · exact hVal)) + | expr_tstore slotExpr valExpr hSlot hVal => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_nativeEvalArgs_preserves + name expected [slotExpr, valExpr] codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected [slotExpr, valExpr] codeOverride + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hSlot + · exact hVal)) + | expr_mstore offsetExpr valExpr hOffset hVal => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_nativeEvalArgs_preserves + name expected [offsetExpr, valExpr] codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected [offsetExpr, valExpr] codeOverride + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hVal)) + | expr_mstore8 offsetExpr valExpr hOffset hVal => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_nativeEvalArgs_preserves + name expected [offsetExpr, valExpr] codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected [offsetExpr, valExpr] codeOverride + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hVal)) + | expr_stop => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact NativeStmtPreservesWord_exprStmtCall_lowerExprNative_stop + name expected codeOverride + | expr_return offsetExpr sizeExpr hOffset hSize => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_nativeEvalArgs_preserves + name expected [offsetExpr, sizeExpr] codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected [offsetExpr, sizeExpr] codeOverride + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hSize)) + | expr_revert offsetExpr sizeExpr hOffset hSize => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_nativeEvalArgs_preserves + name expected [offsetExpr, sizeExpr] codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected [offsetExpr, sizeExpr] codeOverride + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl + · exact hOffset + · exact hSize)) + | expr_log0 args hArgs => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_nativeEvalArgs_preserves + name expected args codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected args codeOverride hArgs) + | expr_log1 args hArgs => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_nativeEvalArgs_preserves + name expected args codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected args codeOverride hArgs) + | expr_log2 args hArgs => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_nativeEvalArgs_preserves + name expected args codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected args codeOverride hArgs) + | expr_log3 args hArgs => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_nativeEvalArgs_preserves + name expected args codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected args codeOverride hArgs) + | expr_log4 args hArgs => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_nativeEvalArgs_preserves + name expected args codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected args codeOverride hArgs) + | expr_calldatacopy destOffset sourceOffset sizeExpr hDest hSource hSize => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_nativeEvalArgs_preserves + name expected [destOffset, sourceOffset, sizeExpr] codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected [destOffset, sourceOffset, sizeExpr] codeOverride + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl | rfl + · exact hDest + · exact hSource + · exact hSize)) + | expr_returndatacopy destOffset sourceOffset sizeExpr hDest hSource hSize => + rw [Backends.lowerStmtGroupNativeWithSwitchIds_expr] at hLower + cases hLower + simp at hMem + subst nativeStmt + exact + NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_nativeEvalArgs_preserves + name expected [destOffset, sourceOffset, sizeExpr] codeOverride + (NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs + name expected [destOffset, sourceOffset, sizeExpr] codeOverride + (by + intro arg hArg + simp at hArg + rcases hArg with rfl | rfl | rfl + · exact hDest + · exact hSource + · exact hSize)) + +theorem NativeStmtPreservesWord_of_mem_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (stmts : List YulStmt) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (hStmts : NativeMappingFreePreservableStraightStmts stmts) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames nextSwitchId stmts = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hFresh : name ∉ Backends.nativeStmtWriteNames nativeStmt) : + NativeStmtPreservesWord name expected nativeStmt codeOverride := by + induction stmts generalizing nextSwitchId native finalSwitchId with | nil => - simp [nativeSwitchCaseIfs, EvmYul.Yul.exec] - | cons entry rest ih => - rcases entry with ⟨tag, body⟩ - have hHeadMiss : state[discrName]! ≠ EvmYul.UInt256.ofNat tag := by - exact hMiss tag body (by simp) - have hRestMiss : - ∀ tag' body', (tag', body') ∈ rest → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := by - intro tag' body' hmem - exact hMiss tag' body' (by simp [hmem]) - have hHead : - EvmYul.Yul.exec (fuel + rest.length + 9) - (nativeSwitchCaseIf discrName matchedName (tag, body)) - codeOverride state = .ok state := by - simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using - (exec_if_nativeSwitchGuardedMatch_miss_fuel - (fuel + rest.length) (Backends.lowerAssignNative matchedName (.lit 1) :: body) - codeOverride state discrName matchedName tag hMatched hHeadMiss) - have hTail : - EvmYul.Yul.exec (fuel + rest.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName rest)) - codeOverride state = .ok state := - ih fuel codeOverride state discrName matchedName hMatched hRestMiss - have hBlock := exec_block_cons_ok (fuel + rest.length + 9) - (nativeSwitchCaseIf discrName matchedName (tag, body)) - (nativeSwitchCaseIfs discrName matchedName rest) - codeOverride state state state hHead hTail - simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using hBlock - -/-- Once a selected lowered switch body preserves the matched flag at one, every - later generated case guard skips. -/ -theorem exec_nativeSwitchCaseIfs_matched_fuel - (fuel : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + rw [Backends.lowerStmtsNativeWithSwitchIds_nil] at hLower + cases hLower + simp at hMem + | cons stmt rest ih => + rw [Backends.lowerStmtsNativeWithSwitchIds_cons] at hLower + cases hHeadLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId stmt with + | error err => + rw [hHeadLower] at hLower + simp only [Bind.bind, Except.bind, reduceCtorEq] at hLower + | ok headPair => + rcases headPair with ⟨headNative, midSwitchId⟩ + rw [hHeadLower] at hLower + simp only [Bind.bind, Except.bind] at hLower + cases hRestLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames midSwitchId rest with + | error err => + rw [hRestLower] at hLower + simp only [reduceCtorEq] at hLower + | ok restPair => + rcases restPair with ⟨restNative, restSwitchId⟩ + rw [hRestLower] at hLower + simp only [Pure.pure, Except.pure, Except.ok.injEq, + Prod.mk.injEq] at hLower + obtain ⟨hNative, hFinal⟩ := hLower + subst hNative + subst hFinal + rw [List.mem_append] at hMem + rcases hMem with hMem | hMem + · exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_of_mappingFreePreservableStraightStmt + name expected reservedNames nextSwitchId stmt headNative + midSwitchId nativeStmt codeOverride + (hStmts stmt (by simp)) hHeadLower hMem hFresh + · exact + ih midSwitchId restNative restSwitchId + (by + intro restStmt hRestMem + exact hStmts restStmt (by simp [hRestMem])) + hRestLower hMem + +theorem NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (stmts : List YulStmt) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 1) : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .ok state := by - induction cases generalizing fuel codeOverride state discrName matchedName with + (hStmts : NativeMappingFreePreservableStraightStmts stmts) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames nextSwitchId stmts = + .ok (native, finalSwitchId)) + (hFresh : name ∉ Backends.nativeStmtsWriteNames native) : + NativeBlockPreservesWord name expected native codeOverride := + NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem name expected native + codeOverride hFresh + (by + intro nativeStmt hMem hStmtFresh + exact + NativeStmtPreservesWord_of_mem_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts + name expected reservedNames nextSwitchId stmts native finalSwitchId + nativeStmt codeOverride hStmts hLower hMem hStmtFresh) + +theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_of_nativePreservableStraightStmt + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (stmt : YulStmt) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hStmt : NativePreservableStraightStmt stmt) + (hLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId stmt = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hFresh : name ∉ Backends.nativeStmtWriteNames nativeStmt) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + induction hStmt with + | comment text => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_comment + name expected reservedNames nextSwitchId text native finalSwitchId + dispatcher nativeStmt hLower hMem + | let_ target value hValue => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_let_of_write_not_mem + name expected reservedNames nextSwitchId target value native finalSwitchId + dispatcher nativeStmt hValue hLower hMem hFresh + | letMany targets value hTargets hValue => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_letMany_of_write_not_mem + name expected reservedNames nextSwitchId targets value native finalSwitchId + dispatcher nativeStmt hTargets hValue hLower hMem hFresh + | assign target value hValue => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_assign_of_write_not_mem + name expected reservedNames nextSwitchId target value native finalSwitchId + dispatcher nativeStmt hValue hLower hMem hFresh + | expr_call func args hName hArgs => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_call_of_bridgedExpr_mappingContract + name expected reservedNames nextSwitchId func args native finalSwitchId + dispatcher nativeStmt hName hArgs hLower hMem + | expr_sstore slotExpr valExpr hSlot hVal => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_sstore_of_nativeEvalArgs + name expected reservedNames nextSwitchId slotExpr valExpr native + finalSwitchId dispatcher nativeStmt hSlot hVal hLower hMem + | expr_tstore slotExpr valExpr hSlot hVal => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_tstore_of_nativeEvalArgs + name expected reservedNames nextSwitchId slotExpr valExpr native + finalSwitchId dispatcher nativeStmt hSlot hVal hLower hMem + | expr_mstore offsetExpr valExpr hOffset hVal => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_mstore_of_nativeEvalArgs + name expected reservedNames nextSwitchId offsetExpr valExpr native + finalSwitchId dispatcher nativeStmt hOffset hVal hLower hMem + | expr_mstore8 offsetExpr valExpr hOffset hVal => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_mstore8_of_nativeEvalArgs + name expected reservedNames nextSwitchId offsetExpr valExpr native + finalSwitchId dispatcher nativeStmt hOffset hVal hLower hMem + | expr_stop => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_stop + name expected reservedNames nextSwitchId native finalSwitchId + dispatcher nativeStmt hLower hMem + | expr_return offsetExpr sizeExpr hOffset hSize => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_return_of_nativeEvalArgs + name expected reservedNames nextSwitchId offsetExpr sizeExpr native + finalSwitchId dispatcher nativeStmt hOffset hSize hLower hMem + | expr_revert offsetExpr sizeExpr hOffset hSize => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_revert_of_nativeEvalArgs + name expected reservedNames nextSwitchId offsetExpr sizeExpr native + finalSwitchId dispatcher nativeStmt hOffset hSize hLower hMem + | expr_log0 args hArgs => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log0_of_nativeEvalArgs + name expected reservedNames nextSwitchId args native finalSwitchId + dispatcher nativeStmt hArgs hLower hMem + | expr_log1 args hArgs => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log1_of_nativeEvalArgs + name expected reservedNames nextSwitchId args native finalSwitchId + dispatcher nativeStmt hArgs hLower hMem + | expr_log2 args hArgs => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log2_of_nativeEvalArgs + name expected reservedNames nextSwitchId args native finalSwitchId + dispatcher nativeStmt hArgs hLower hMem + | expr_log3 args hArgs => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log3_of_nativeEvalArgs + name expected reservedNames nextSwitchId args native finalSwitchId + dispatcher nativeStmt hArgs hLower hMem + | expr_log4 args hArgs => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log4_of_nativeEvalArgs + name expected reservedNames nextSwitchId args native finalSwitchId + dispatcher nativeStmt hArgs hLower hMem + | expr_calldatacopy destOffset sourceOffset sizeExpr hDest hSource hSize => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_calldatacopy_of_nativeEvalArgs + name expected reservedNames nextSwitchId destOffset sourceOffset sizeExpr + native finalSwitchId dispatcher nativeStmt hDest hSource hSize hLower hMem + | expr_returndatacopy destOffset sourceOffset sizeExpr hDest hSource hSize => + exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_returndatacopy_of_nativeEvalArgs + name expected reservedNames nextSwitchId destOffset sourceOffset sizeExpr + native finalSwitchId dispatcher nativeStmt hDest hSource hSize hLower hMem + +theorem NativeStmtPreservesWord_of_mem_lowerStmtsNativeWithSwitchIds_of_nativePreservableStraightStmts + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (stmts : List YulStmt) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hStmts : NativePreservableStraightStmts stmts) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames nextSwitchId stmts = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hFresh : name ∉ Backends.nativeStmtWriteNames nativeStmt) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := by + induction stmts generalizing nextSwitchId native finalSwitchId with | nil => - simp [nativeSwitchCaseIfs, EvmYul.Yul.exec] - | cons entry rest ih => - rcases entry with ⟨tag, body⟩ - have hHead : - EvmYul.Yul.exec (fuel + rest.length + 9) - (nativeSwitchCaseIf discrName matchedName (tag, body)) - codeOverride state = .ok state := by - simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using - (exec_if_nativeSwitchGuardedMatch_matched_fuel - (fuel + rest.length) (Backends.lowerAssignNative matchedName (.lit 1) :: body) - codeOverride state discrName matchedName tag hMatched) - have hTail : - EvmYul.Yul.exec (fuel + rest.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName rest)) - codeOverride state = .ok state := - ih fuel codeOverride state discrName matchedName hMatched - have hBlock := exec_block_cons_ok (fuel + rest.length + 9) - (nativeSwitchCaseIf discrName matchedName (tag, body)) - (nativeSwitchCaseIfs discrName matchedName rest) - codeOverride state state state hHead hTail - simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using hBlock + rw [Backends.lowerStmtsNativeWithSwitchIds_nil] at hLower + cases hLower + simp at hMem + | cons stmt rest ih => + rw [Backends.lowerStmtsNativeWithSwitchIds_cons] at hLower + cases hHeadLower : + Backends.lowerStmtGroupNativeWithSwitchIds reservedNames nextSwitchId stmt with + | error err => + rw [hHeadLower] at hLower + simp only [Bind.bind, Except.bind, reduceCtorEq] at hLower + | ok headPair => + rcases headPair with ⟨headNative, midSwitchId⟩ + rw [hHeadLower] at hLower + simp only [Bind.bind, Except.bind] at hLower + cases hRestLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames midSwitchId rest with + | error err => + rw [hRestLower] at hLower + simp only [reduceCtorEq] at hLower + | ok restPair => + rcases restPair with ⟨restNative, restSwitchId⟩ + rw [hRestLower] at hLower + simp only [Pure.pure, Except.pure, Except.ok.injEq, + Prod.mk.injEq] at hLower + obtain ⟨hNative, hFinal⟩ := hLower + subst hNative + subst hFinal + rw [List.mem_append] at hMem + rcases hMem with hMem | hMem + · exact + NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_of_nativePreservableStraightStmt + name expected reservedNames nextSwitchId stmt headNative + midSwitchId dispatcher nativeStmt + (hStmts stmt (by simp)) hHeadLower hMem hFresh + · exact + ih midSwitchId restNative restSwitchId + (by + intro restStmt hRestMem + exact hStmts restStmt (by simp [hRestMem])) + hRestLower hMem + +theorem NativeStmtPreservesWord_of_mem_lowerStmtsNativeWithSwitchIds_of_bridgedStraightStmts + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (stmts : List YulStmt) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (nativeStmt : EvmYul.Yul.Ast.Stmt) + (hStmts : + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts stmts) + (hSide : + ∀ stmt, stmt ∈ stmts → + NativePreservableSideConditionForBridgedStraightStmt stmt) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames nextSwitchId stmts = + .ok (native, finalSwitchId)) + (hMem : nativeStmt ∈ native) + (hFresh : name ∉ Backends.nativeStmtWriteNames nativeStmt) : + NativeStmtPreservesWord name expected nativeStmt + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeStmtPreservesWord_of_mem_lowerStmtsNativeWithSwitchIds_of_nativePreservableStraightStmts + name expected reservedNames nextSwitchId stmts native finalSwitchId + dispatcher nativeStmt + (NativePreservableStraightStmts.of_bridgedStraightStmts hStmts hSide) + hLower hMem hFresh + +theorem NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_nativePreservableStraightStmts + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (stmts : List YulStmt) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hStmts : NativePreservableStraightStmts stmts) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames nextSwitchId stmts = + .ok (native, finalSwitchId)) + (hFresh : name ∉ Backends.nativeStmtsWriteNames native) : + NativeBlockPreservesWord name expected native + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem name expected native + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) + hFresh + (by + intro nativeStmt hMem hStmtFresh + exact + NativeStmtPreservesWord_of_mem_lowerStmtsNativeWithSwitchIds_of_nativePreservableStraightStmts + name expected reservedNames nextSwitchId stmts native finalSwitchId + dispatcher nativeStmt hStmts hLower hMem hStmtFresh) + +/-- Lowered straight bridged statement lists preserve a marker word under the +native EVMYulLean harness, once the small native-preservation side conditions +are supplied. + +This packages the historical bridged-straight predicate conversion together +with the native lowering preservation theorem. Selector-hit success proofs can +use this directly after extracting no-write freshness for the selected lowered +body. -/ +theorem NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_bridgedStraightStmts + (name : EvmYul.Identifier) + (expected : EvmYul.Literal) + (reservedNames : List String) + (nextSwitchId : Nat) + (stmts : List YulStmt) + (native : List EvmYul.Yul.Ast.Stmt) + (finalSwitchId : Nat) + (dispatcher : EvmYul.Yul.Ast.Stmt) + (hStmts : + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts stmts) + (hSide : + ∀ stmt, stmt ∈ stmts → + NativePreservableSideConditionForBridgedStraightStmt stmt) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames nextSwitchId stmts = + .ok (native, finalSwitchId)) + (hFresh : name ∉ Backends.nativeStmtsWriteNames native) : + NativeBlockPreservesWord name expected native + (some + { dispatcher := dispatcher + functions := ((∅ : NativeFunctionMap).insert + "mappingSlot" nativeMappingSlotFunctionDefinition) }) := + NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_nativePreservableStraightStmts + name expected reservedNames nextSwitchId stmts native finalSwitchId + dispatcher + (NativePreservableStraightStmts.of_bridgedStraightStmts hStmts hSide) + hLower hFresh -/-- Whole generated case-chain execution when the first remaining case is the - selected case and suffix cases must skip after the selected body preserves - the matched flag. -/ -theorem exec_nativeSwitchCaseIfs_head_hit_fuel - (fuel : Nat) - (suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state final : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hDiscr : state[discrName]! = EvmYul.UInt256.ofNat tag) - (hBody : - EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride - (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = .ok final) - (hFinalMatched : final[matchedName]! = EvmYul.UInt256.ofNat 1) : - EvmYul.Yul.exec (fuel + suffix.length + 10) - (.Block - (nativeSwitchCaseIfs discrName matchedName ((tag, body) :: suffix))) - codeOverride state = .ok final := by - have hHead : - EvmYul.Yul.exec (fuel + suffix.length + 9) - (nativeSwitchCaseIf discrName matchedName (tag, body)) - codeOverride state = .ok final := by - simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using - (exec_if_nativeSwitchGuardedMatch_hit_marked_fuel - (fuel + suffix.length) body codeOverride state final discrName - matchedName tag hMatched hDiscr hBody) - have hTail : - EvmYul.Yul.exec (fuel + suffix.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName suffix)) - codeOverride final = .ok final := - exec_nativeSwitchCaseIfs_matched_fuel fuel suffix codeOverride final - discrName matchedName hFinalMatched - have hBlock := exec_block_cons_ok (fuel + suffix.length + 9) - (nativeSwitchCaseIf discrName matchedName (tag, body)) - (nativeSwitchCaseIfs discrName matchedName suffix) - codeOverride state final final hHead hTail - simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using hBlock +theorem nativeSwitchTempsFreshForNativeBodies_case_matched_not_mem + (switchId tag : Nat) + (body defaultBody : List EvmYul.Yul.Ast.Stmt) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hMem : (tag, body) ∈ cases) : + Backends.nativeSwitchMatchedTempName switchId ∉ + Backends.nativeStmtsWriteNames body := + (hFresh.1 tag body hMem).2 -/-- Whole generated case-chain execution when the first remaining case is the - selected case and that selected body halts or errors before the suffix can - run. -/ -theorem exec_nativeSwitchCaseIfs_head_hit_error_fuel - (fuel : Nat) - (suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (err : EvmYul.Yul.Exception) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hDiscr : state[discrName]! = EvmYul.UInt256.ofNat tag) - (hBody : - EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride - (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = .error err) : - EvmYul.Yul.exec (fuel + suffix.length + 10) - (.Block - (nativeSwitchCaseIfs discrName matchedName ((tag, body) :: suffix))) - codeOverride state = .error err := by - have hHead : - EvmYul.Yul.exec (fuel + suffix.length + 9) - (nativeSwitchCaseIf discrName matchedName (tag, body)) - codeOverride state = .error err := by - simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using - (exec_if_nativeSwitchGuardedMatch_hit_marked_error_fuel - (fuel + suffix.length) body codeOverride state discrName matchedName - tag err hMatched hDiscr hBody) - have hBlock := - exec_block_cons_error (fuel + suffix.length + 9) - (nativeSwitchCaseIf discrName matchedName (tag, body)) - (nativeSwitchCaseIfs discrName matchedName suffix) - codeOverride state err hHead - simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using hBlock +theorem nativeSwitchTempsFreshForNativeBodies_case_discr_not_mem + (switchId tag : Nat) + (body defaultBody : List EvmYul.Yul.Ast.Stmt) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hMem : (tag, body) ∈ cases) : + Backends.nativeSwitchDiscrTempName switchId ∉ + Backends.nativeStmtsWriteNames body := + (hFresh.1 tag body hMem).1 -/-- Cons a non-selected generated switch case onto an already-proved generated - case-chain execution. -/ -theorem exec_nativeSwitchCaseIfs_cons_miss_fuel - (fuel : Nat) - (rest : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (missTag : Nat) - (missBody : List EvmYul.Yul.Ast.Stmt) +theorem nativeSwitchTempsFreshForNativeBodies_find_hit_matched_not_mem + (switchId selector tag : Nat) + (body defaultBody : List EvmYul.Yul.Ast.Stmt) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) : + Backends.nativeSwitchMatchedTempName switchId ∉ + Backends.nativeStmtsWriteNames body := by + have hMem : (tag, body) ∈ cases := by + clear hFresh + induction cases with + | nil => + simp [List.find?] at hFind + | cons head rest ih => + cases hHead : (head.1 == selector) + · simp [List.find?, hHead] at hFind + exact List.mem_cons_of_mem head (ih hFind) + · simp [List.find?, hHead] at hFind + simp [hFind] + exact nativeSwitchTempsFreshForNativeBodies_case_matched_not_mem + switchId tag body defaultBody cases hFresh hMem + +theorem nativeSwitchTempsFreshForNativeBodies_find_hit_discr_not_mem + (switchId selector tag : Nat) + (body defaultBody : List EvmYul.Yul.Ast.Stmt) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) : + Backends.nativeSwitchDiscrTempName switchId ∉ + Backends.nativeStmtsWriteNames body := by + have hMem : (tag, body) ∈ cases := by + clear hFresh + induction cases with + | nil => + simp [List.find?] at hFind + | cons head rest ih => + cases hHead : (head.1 == selector) + · simp [List.find?, hHead] at hFind + exact List.mem_cons_of_mem head (ih hFind) + · simp [List.find?, hHead] at hFind + simp [hFind] + exact nativeSwitchTempsFreshForNativeBodies_case_discr_not_mem + switchId tag body defaultBody cases hFresh hMem + +theorem nativeSwitchTempsFreshForNativeBodies_default_matched_not_mem + (switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) : + Backends.nativeSwitchMatchedTempName switchId ∉ + Backends.nativeStmtsWriteNames defaultBody := + hFresh.2.2 + +theorem nativeSwitchTempsFreshForNativeBodies_default_discr_not_mem + (switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) : + Backends.nativeSwitchDiscrTempName switchId ∉ + Backends.nativeStmtsWriteNames defaultBody := + hFresh.2.1 + +theorem NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + (switchId selector tag : Nat) + (body defaultBody : List EvmYul.Yul.Ast.Stmt) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (expected : EvmYul.Literal) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state final : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hHeadMiss : state[discrName]! ≠ EvmYul.UInt256.ofNat missTag) - (hTail : - EvmYul.Yul.exec (fuel + rest.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName rest)) - codeOverride state = .ok final) : - EvmYul.Yul.exec (fuel + rest.length + 10) - (.Block - (nativeSwitchCaseIfs discrName matchedName - ((missTag, missBody) :: rest))) - codeOverride state = .ok final := by - have hHead : - EvmYul.Yul.exec (fuel + rest.length + 9) - (nativeSwitchCaseIf discrName matchedName (missTag, missBody)) - codeOverride state = .ok state := by - simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using - (exec_if_nativeSwitchGuardedMatch_miss_fuel - (fuel + rest.length) - (Backends.lowerAssignNative matchedName (.lit 1) :: missBody) - codeOverride state discrName matchedName missTag hMatched hHeadMiss) - have hBlock := exec_block_cons_ok (fuel + rest.length + 9) - (nativeSwitchCaseIf discrName matchedName (missTag, missBody)) - (nativeSwitchCaseIfs discrName matchedName rest) - codeOverride state state final hHead hTail - simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using hBlock + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) + (hStmtPreserves : + ∀ stmt, stmt ∈ body → + Backends.nativeSwitchMatchedTempName switchId ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + expected stmt codeOverride) : + NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + expected body codeOverride := + NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem + (Backends.nativeSwitchMatchedTempName switchId) expected body codeOverride + (nativeSwitchTempsFreshForNativeBodies_find_hit_matched_not_mem + switchId selector tag body defaultBody cases hFresh hFind) + hStmtPreserves -/-- Whole generated case-chain execution for a miss prefix, selected case, and suffix. -/ -theorem exec_nativeSwitchCaseIfs_prefix_hit_fuel - (fuel : Nat) - (pre suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (tag : Nat) (body : List EvmYul.Yul.Ast.Stmt) +theorem NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_discr + (switchId selector tag : Nat) + (body defaultBody : List EvmYul.Yul.Ast.Stmt) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (expected : EvmYul.Literal) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state final : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hMissPrefix : ∀ tag' body', (tag', body') ∈ pre → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag') - (hDiscr : state[discrName]! = EvmYul.UInt256.ofNat tag) - (hBody : - EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride - (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = .ok final) - (hFinalMatched : final[matchedName]! = EvmYul.UInt256.ofNat 1) : - EvmYul.Yul.exec (fuel + (pre ++ (tag, body) :: suffix).length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName - (pre ++ (tag, body) :: suffix))) - codeOverride state = .ok final := by - induction pre generalizing fuel with - | nil => - simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using - (exec_nativeSwitchCaseIfs_head_hit_fuel fuel suffix tag body codeOverride - state final discrName matchedName hMatched hDiscr hBody hFinalMatched) - | cons entry rest ih => - rcases entry with ⟨missTag, missBody⟩ - have hHeadMiss : - state[discrName]! ≠ EvmYul.UInt256.ofNat missTag := by - exact hMissPrefix missTag missBody (by simp) - have hRestMiss : - ∀ tag' body', (tag', body') ∈ rest → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := by - intro tag' body' hmem - exact hMissPrefix tag' body' (by simp [hmem]) - have hTail : - EvmYul.Yul.exec - (fuel + (rest ++ (tag, body) :: suffix).length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName - (rest ++ (tag, body) :: suffix))) - codeOverride state = .ok final := - ih fuel hRestMiss hBody - simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using - (exec_nativeSwitchCaseIfs_cons_miss_fuel fuel - (rest ++ (tag, body) :: suffix) missTag missBody codeOverride state - final discrName matchedName hMatched hHeadMiss hTail) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) + (hStmtPreserves : + ∀ stmt, stmt ∈ body → + Backends.nativeSwitchDiscrTempName switchId ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchDiscrTempName switchId) + expected stmt codeOverride) : + NativeBlockPreservesWord (Backends.nativeSwitchDiscrTempName switchId) + expected body codeOverride := + NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem + (Backends.nativeSwitchDiscrTempName switchId) expected body codeOverride + (nativeSwitchTempsFreshForNativeBodies_find_hit_discr_not_mem + switchId selector tag body defaultBody cases hFresh hFind) + hStmtPreserves -/-- Whole generated case-chain execution for a miss prefix, selected case, and - suffix when the selected case halts or errors. -/ -theorem exec_nativeSwitchCaseIfs_prefix_hit_error_fuel - (fuel : Nat) - (pre suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (tag : Nat) (body : List EvmYul.Yul.Ast.Stmt) +theorem NativeBlockPreservesWord_of_nativeSwitchFresh_default_matched + (switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (expected : EvmYul.Literal) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (err : EvmYul.Yul.Exception) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hMissPrefix : ∀ tag' body', (tag', body') ∈ pre → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag') - (hDiscr : state[discrName]! = EvmYul.UInt256.ofNat tag) - (hBody : - EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride - (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = .error err) : - EvmYul.Yul.exec (fuel + (pre ++ (tag, body) :: suffix).length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName - (pre ++ (tag, body) :: suffix))) - codeOverride state = .error err := by - induction pre generalizing fuel with - | nil => - simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using - (exec_nativeSwitchCaseIfs_head_hit_error_fuel fuel suffix tag body - codeOverride state discrName matchedName err hMatched hDiscr hBody) - | cons entry rest ih => - rcases entry with ⟨missTag, missBody⟩ - have hHeadMiss : - state[discrName]! ≠ EvmYul.UInt256.ofNat missTag := by - exact hMissPrefix missTag missBody (by simp) - have hRestMiss : - ∀ tag' body', (tag', body') ∈ rest → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := by - intro tag' body' hmem - exact hMissPrefix tag' body' (by simp [hmem]) - have hTail : - EvmYul.Yul.exec - (fuel + (rest ++ (tag, body) :: suffix).length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName - (rest ++ (tag, body) :: suffix))) - codeOverride state = .error err := - ih fuel hRestMiss hBody - have hHead : - EvmYul.Yul.exec - (fuel + (rest ++ (tag, body) :: suffix).length + 9) - (nativeSwitchCaseIf discrName matchedName (missTag, missBody)) - codeOverride state = .ok state := by - simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using - (exec_if_nativeSwitchGuardedMatch_miss_fuel - (fuel + (rest ++ (tag, body) :: suffix).length) - (Backends.lowerAssignNative matchedName (.lit 1) :: missBody) - codeOverride state discrName matchedName missTag hMatched hHeadMiss) - simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using - (exec_block_cons_tail_error - (fuel + (rest ++ (tag, body) :: suffix).length + 9) - (nativeSwitchCaseIf discrName matchedName (missTag, missBody)) - (nativeSwitchCaseIfs discrName matchedName - (rest ++ (tag, body) :: suffix)) - codeOverride state state err hHead hTail) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hStmtPreserves : + ∀ stmt, stmt ∈ defaultBody → + Backends.nativeSwitchMatchedTempName switchId ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + expected stmt codeOverride) : + NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + expected defaultBody codeOverride := + NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem + (Backends.nativeSwitchMatchedTempName switchId) expected defaultBody + codeOverride + (nativeSwitchTempsFreshForNativeBodies_default_matched_not_mem + switchId cases defaultBody hFresh) + hStmtPreserves -/-- Whole generated case-chain execution for a selector lookup hit. This wraps - `exec_nativeSwitchCaseIfs_prefix_hit_fuel` with the generated dispatcher - lookup split, so callers only need the `find?` result and the selected body - execution premise for the discovered suffix. -/ -theorem exec_nativeSwitchCaseIfs_find_hit_fuel - (fuel selector : Nat) +theorem NativeBlockPreservesWord_of_nativeSwitchFresh_default_discr + (switchId : Nat) (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (expected : EvmYul.Literal) (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state final : EvmYul.Yul.State) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hStmtPreserves : + ∀ stmt, stmt ∈ defaultBody → + Backends.nativeSwitchDiscrTempName switchId ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchDiscrTempName switchId) + expected stmt codeOverride) : + NativeBlockPreservesWord (Backends.nativeSwitchDiscrTempName switchId) + expected defaultBody codeOverride := + NativeBlockPreservesWord_of_nativeStmtsWriteNames_not_mem + (Backends.nativeSwitchDiscrTempName switchId) expected defaultBody + codeOverride + (nativeSwitchTempsFreshForNativeBodies_default_discr_not_mem + switchId cases defaultBody hFresh) + hStmtPreserves + +@[simp] theorem nativeSwitchCaseIfs_nil + (discrName matchedName : EvmYul.Identifier) : + nativeSwitchCaseIfs discrName matchedName [] = [] := by + rfl + +@[simp] theorem nativeSwitchCaseIfs_cons (discrName matchedName : EvmYul.Identifier) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hBody : - ∀ pre suffix, - cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) - codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = - .ok final) - (hFinalMatched : final[matchedName]! = EvmYul.UInt256.ofNat 1) : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .ok final := by - rcases nativeSwitch_find_hit_split selector cases tag body hFind with - ⟨pre, suffix, hCases, hTag, hPrefix⟩ - subst tag - have hMissPrefix : - ∀ tag' body', (tag', body') ∈ pre → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := - nativeSwitch_prefix_miss_of_selector_find selector cases pre suffix selector body - state discrName hCases hPrefix hDiscrSelector hSelectorRange hTagsRange - have hSelectedBody : - EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) - codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = - .ok final := - hBody pre suffix hCases - have hExec := - exec_nativeSwitchCaseIfs_prefix_hit_fuel fuel pre suffix selector body - codeOverride state final discrName matchedName hMatched hMissPrefix - hDiscrSelector hSelectedBody hFinalMatched - simpa [hCases, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hExec + (entry : Nat × List EvmYul.Yul.Ast.Stmt) + (rest : List (Nat × List EvmYul.Yul.Ast.Stmt)) : + nativeSwitchCaseIfs discrName matchedName (entry :: rest) = + nativeSwitchCaseIf discrName matchedName entry :: + nativeSwitchCaseIfs discrName matchedName rest := by + rfl -/-- Whole generated case-chain execution for a selector lookup hit whose - selected body halts or errors. -/ -theorem exec_nativeSwitchCaseIfs_find_hit_error_fuel - (fuel selector : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) +private theorem list_find?_eq_some_split_false + {α : Type} + (p : α → Bool) : + ∀ {xs : List α} {x : α}, + xs.find? p = some x → + ∃ pre suffix, + xs = pre ++ x :: suffix ∧ + ∀ y, y ∈ pre → p y = false + | [], _, hFind => by + simp [List.find?] at hFind + | y :: ys, x, hFind => by + by_cases hp : p y = true + · have hxy : x = y := by + simpa [List.find?, hp] using hFind.symm + subst x + exact ⟨[], ys, by simp, by simp⟩ + · have hFalse : p y = false := Bool.eq_false_iff.2 hp + have hRest : ys.find? p = some x := by + simpa [List.find?, hFalse] using hFind + rcases list_find?_eq_some_split_false p hRest with + ⟨pre, suffix, hSplit, hPre⟩ + refine ⟨y :: pre, suffix, ?_, ?_⟩ + · simp [hSplit] + · intro z hz + have hz' : z = y ∨ z ∈ pre := by + simpa [List.mem_cons] using hz + rcases hz' with hzy | hzPre + · cases hzy + exact hFalse + · exact hPre z hzPre + +private theorem list_find?_eq_none_all_false + {α : Type} + (p : α → Bool) : + ∀ {xs : List α}, + xs.find? p = none → + ∀ x, x ∈ xs → p x = false + | [], hFind, x, hx => by + simp at hx + | y :: ys, hFind, x, hx => by + by_cases hp : p y = true + · simp [List.find?, hp] at hFind + · have hFalse : p y = false := Bool.eq_false_iff.2 hp + have hRest : ys.find? p = none := by + simpa [List.find?, hFalse] using hFind + have hx' : x = y ∨ x ∈ ys := by + simpa [List.mem_cons] using hx + rcases hx' with hxy | hxTail + · cases hxy + exact hFalse + · exact list_find?_eq_none_all_false p hRest x hxTail + +private theorem uint256_ofNat_ne_of_ne_of_lt + {a b : Nat} + (ha : a < EvmYul.UInt256.size) + (hb : b < EvmYul.UInt256.size) + (hne : a ≠ b) : + EvmYul.UInt256.ofNat a ≠ EvmYul.UInt256.ofNat b := by + intro h + apply hne + have hToNat := congrArg EvmYul.UInt256.toNat h + rw [uint256_ofNat_toNat_of_lt a ha, + uint256_ofNat_toNat_of_lt b hb] at hToNat + exact hToNat + +private theorem nativeSwitch_prefix_miss_of_selector_find + (selector : Nat) + (cases pre suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)) (tag : Nat) (body : List EvmYul.Yul.Ast.Stmt) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) (state : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (err : EvmYul.Yul.Exception) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hBody : - ∀ pre suffix, - cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) - codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = - .error err) : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .error err := by - rcases nativeSwitch_find_hit_split selector cases tag body hFind with - ⟨pre, suffix, hCases, hTag, hPrefix⟩ - subst tag - have hMissPrefix : - ∀ tag' body', (tag', body') ∈ pre → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := - nativeSwitch_prefix_miss_of_selector_find selector cases pre suffix selector body - state discrName hCases hPrefix hDiscrSelector hSelectorRange hTagsRange - have hSelectedBody : - EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) - codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = - .error err := - hBody pre suffix hCases - have hExec := - exec_nativeSwitchCaseIfs_prefix_hit_error_fuel fuel pre suffix selector body - codeOverride state discrName matchedName err hMatched hMissPrefix - hDiscrSelector hSelectedBody - simpa [hCases, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hExec - -/-- Selector-hit case-chain execution with the selected-body matched-flag - preservation obligation factored into a reusable predicate. - -This is the proof boundary needed by the full native dispatcher bridge: the -lowered case body may update storage, memory, and user variables, but it must -not clobber the generated lazy-switch matched flag after the lowering has set -it to one. -/ -theorem exec_nativeSwitchCaseIfs_find_hit_preserved_fuel - (fuel selector : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state final : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (hFind : - cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (discrName : EvmYul.Identifier) + (hCases : cases = pre ++ (tag, body) :: suffix) + (hPrefix : + ∀ entry, entry ∈ pre → (fun entry : Nat × List EvmYul.Yul.Ast.Stmt => + entry.1 == selector) entry = false) (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) (hSelectorRange : selector < EvmYul.UInt256.size) (hTagsRange : - ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hMarked : - (state.insert matchedName (EvmYul.UInt256.ofNat 1))[matchedName]! = - EvmYul.UInt256.ofNat 1) - (hBody : - ∀ pre suffix, - cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) - codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = - .ok final) - (hPreservesMatched : - ∀ pre suffix, - cases = pre ++ (tag, body) :: suffix → - NativeBlockPreservesWord matchedName (EvmYul.UInt256.ofNat 1) - body codeOverride) : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .ok final := by - apply exec_nativeSwitchCaseIfs_find_hit_fuel - (fuel := fuel) (selector := selector) (cases := cases) (tag := tag) - (body := body) (codeOverride := codeOverride) (state := state) - (final := final) (discrName := discrName) (matchedName := matchedName) - hFind hMatched hDiscrSelector hSelectorRange hTagsRange hBody - rcases nativeSwitch_find_hit_split selector cases tag body hFind with - ⟨pre, suffix, hCases, _hTag, _hPrefix⟩ - exact hPreservesMatched pre suffix hCases (fuel + suffix.length + 7) - (state.insert matchedName (EvmYul.UInt256.ofNat 1)) final hMarked - (hBody pre suffix hCases) + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) : + ∀ tag' body', (tag', body') ∈ pre → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := by + intro tag' body' hmem hDiscrTag + have hPrefixFalse := hPrefix (tag', body') hmem + have hTagNe : tag' ≠ selector := by + intro hEq + have hTrue : (tag' == selector) = true := beq_iff_eq.mpr hEq + have hFalse : (tag' == selector) = false := by + simpa using hPrefixFalse + rw [hTrue] at hFalse + contradiction + have hCaseMem : (tag', body') ∈ cases := by + rw [hCases] + simp [hmem] + have hWordNe : + EvmYul.UInt256.ofNat selector ≠ EvmYul.UInt256.ofNat tag' := + uint256_ofNat_ne_of_ne_of_lt hSelectorRange + (hTagsRange tag' body' hCaseMem) (Ne.symm hTagNe) + exact hWordNe (hDiscrSelector.symm.trans hDiscrTag) -/-- Whole generated case-chain skip for a selector lookup miss. This packages - the `find? = none` selector fact into the all-cases-miss premise expected by - the lazy native switch executor. -/ -theorem exec_nativeSwitchCaseIfs_find_none_fuel - (fuel selector : Nat) +/-- A selector lookup hit exposes the generated case list as a miss prefix, + selected case, and suffix. This is the list-shape bridge consumed by the + native lazy-switch execution lemmas. -/ +theorem nativeSwitch_find_hit_split + (selector : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (hFind : + cases.find? (fun entry => entry.1 == selector) = some (tag, body)) : + ∃ pre suffix, + cases = pre ++ (tag, body) :: suffix ∧ + tag = selector ∧ + ∀ entry, entry ∈ pre → + (fun entry : Nat × List EvmYul.Yul.Ast.Stmt => + entry.1 == selector) entry = false := by + rcases list_find?_eq_some_split_false + (fun entry : Nat × List EvmYul.Yul.Ast.Stmt => entry.1 == selector) + hFind with + ⟨pre, suffix, hSplit, hPrefix⟩ + have hSelected : + (fun entry : Nat × List EvmYul.Yul.Ast.Stmt => + entry.1 == selector) (tag, body) = true := + List.find?_some + (p := fun entry : Nat × List EvmYul.Yul.Ast.Stmt => + entry.1 == selector) hFind + have hTag : tag = selector := by + exact beq_iff_eq.mp hSelected + exact ⟨pre, suffix, hSplit, hTag, hPrefix⟩ + +/-- A selector lookup miss proves every generated case tag misses the native + dispatcher discriminator when the discriminator contains that selector and + all case tags are in the `UInt256` range. -/ +theorem nativeSwitch_find_none_all_miss + (selector : Nat) (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) (state : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) + (discrName : EvmYul.Identifier) (hFind : cases.find? (fun entry => entry.1 == selector) = none) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) (hSelectorRange : selector < EvmYul.UInt256.size) (hTagsRange : ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .ok state := by - have hMiss : - ∀ tag body, (tag, body) ∈ cases → - state[discrName]! ≠ EvmYul.UInt256.ofNat tag := - nativeSwitch_find_none_all_miss selector cases state discrName hFind - hDiscrSelector hSelectorRange hTagsRange - exact exec_nativeSwitchCaseIfs_all_miss_fuel fuel cases codeOverride state - discrName matchedName hMatched hMiss -/-- Non-empty generated default block execution when no case matched. -/ -theorem exec_nativeSwitchDefaultIf_unmatched_nonempty_fuel - (fuel : Nat) - (defaultBody : List EvmYul.Yul.Ast.Stmt) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state final : EvmYul.Yul.State) - (matchedName : EvmYul.Identifier) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hBody : - EvmYul.Yul.exec (fuel + 6) (.Block defaultBody) codeOverride state = - .ok final) - (hNonempty : defaultBody ≠ []) : - EvmYul.Yul.exec (fuel + 8) - (.Block (nativeSwitchDefaultIf matchedName defaultBody)) - codeOverride state = .ok final := by - cases defaultBody with - | nil => contradiction - | cons stmt rest => - have hHead : - EvmYul.Yul.exec (fuel + 7) - (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) - codeOverride state = .ok final := by - simpa [nativeSwitchDefaultGuardExpr] using - (exec_if_nativeSwitchDefaultGuard_unmatched_fuel fuel - (stmt :: rest) codeOverride state final matchedName hMatched hBody) - have hTail : - EvmYul.Yul.exec (fuel + 7) (.Block []) - codeOverride final = .ok final := by - simp [EvmYul.Yul.exec] - exact exec_block_cons_ok (fuel + 7) - (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) - [] codeOverride state final final hHead hTail + ∀ tag body, (tag, body) ∈ cases → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag := by + intro tag body hmem hDiscrTag + have hFalse := + list_find?_eq_none_all_false + (fun entry : Nat × List EvmYul.Yul.Ast.Stmt => entry.1 == selector) + hFind (tag, body) hmem + have hTagNe : tag ≠ selector := by + intro hEq + have hTrue : (tag == selector) = true := beq_iff_eq.mpr hEq + have hFalse' : (tag == selector) = false := by + simpa using hFalse + rw [hTrue] at hFalse' + contradiction + have hWordNe : + EvmYul.UInt256.ofNat selector ≠ EvmYul.UInt256.ofNat tag := + uint256_ofNat_ne_of_ne_of_lt hSelectorRange + (hTagsRange tag body hmem) (Ne.symm hTagNe) + exact hWordNe (hDiscrSelector.symm.trans hDiscrTag) -/-- Non-empty generated default block execution when no case matched and the - default body halts or errors. This is the selector-miss path used by a - default `revert(0, 0)` body. -/ -theorem exec_nativeSwitchDefaultIf_unmatched_nonempty_error_fuel +/-- If no case tag matches and the matched flag is still clear, the generated + native switch case chain skips every case body and leaves the state + unchanged. -/ +theorem exec_nativeSwitchCaseIfs_all_miss_fuel (fuel : Nat) - (defaultBody : List EvmYul.Yul.Ast.Stmt) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (codeOverride : Option EvmYul.Yul.Ast.YulContract) (state : EvmYul.Yul.State) - (matchedName : EvmYul.Identifier) - (err : EvmYul.Yul.Exception) + (discrName matchedName : EvmYul.Identifier) (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hBody : - EvmYul.Yul.exec (fuel + 6) (.Block defaultBody) codeOverride state = - .error err) - (hNonempty : defaultBody ≠ []) : - EvmYul.Yul.exec (fuel + 8) - (.Block (nativeSwitchDefaultIf matchedName defaultBody)) - codeOverride state = .error err := by - cases defaultBody with - | nil => contradiction - | cons stmt rest => + (hMiss : + ∀ tag body, (tag, body) ∈ cases → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag) : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) + codeOverride state = .ok state := by + induction cases generalizing fuel codeOverride state discrName matchedName with + | nil => + simp [nativeSwitchCaseIfs, EvmYul.Yul.exec] + | cons entry rest ih => + rcases entry with ⟨tag, body⟩ + have hHeadMiss : state[discrName]! ≠ EvmYul.UInt256.ofNat tag := by + exact hMiss tag body (by simp) + have hRestMiss : + ∀ tag' body', (tag', body') ∈ rest → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := by + intro tag' body' hmem + exact hMiss tag' body' (by simp [hmem]) have hHead : - EvmYul.Yul.exec (fuel + 7) - (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) - codeOverride state = .error err := by - simpa [nativeSwitchDefaultGuardExpr] using - (exec_if_nativeSwitchDefaultGuard_unmatched_error_fuel fuel - (stmt :: rest) codeOverride state matchedName err hMatched hBody) - exact exec_block_cons_error (fuel + 7) - (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) - [] codeOverride state err hHead + EvmYul.Yul.exec (fuel + rest.length + 9) + (nativeSwitchCaseIf discrName matchedName (tag, body)) + codeOverride state = .ok state := by + simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using + (exec_if_nativeSwitchGuardedMatch_miss_fuel + (fuel + rest.length) (Backends.lowerAssignNative matchedName (.lit 1) :: body) + codeOverride state discrName matchedName tag hMatched hHeadMiss) + have hTail : + EvmYul.Yul.exec (fuel + rest.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName rest)) + codeOverride state = .ok state := + ih fuel codeOverride state discrName matchedName hMatched hRestMiss + have hBlock := exec_block_cons_ok (fuel + rest.length + 9) + (nativeSwitchCaseIf discrName matchedName (tag, body)) + (nativeSwitchCaseIfs discrName matchedName rest) + codeOverride state state state hHead hTail + simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hBlock -/-- After a selected case preserves the matched flag at one, the optional - generated default block skips. Empty defaults also skip because no default - statement is emitted. -/ -theorem exec_nativeSwitchDefaultIf_matched_fuel +/-- Once a selected lowered switch body preserves the matched flag at one, every + later generated case guard skips. -/ +theorem exec_nativeSwitchCaseIfs_matched_fuel (fuel : Nat) - (defaultBody : List EvmYul.Yul.Ast.Stmt) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (codeOverride : Option EvmYul.Yul.Ast.YulContract) (state : EvmYul.Yul.State) - (matchedName : EvmYul.Identifier) + (discrName matchedName : EvmYul.Identifier) (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 1) : - EvmYul.Yul.exec - (fuel + (nativeSwitchDefaultIf matchedName defaultBody).length + 7) - (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) codeOverride state = .ok state := by - cases defaultBody with + induction cases generalizing fuel codeOverride state discrName matchedName with | nil => - simp [nativeSwitchDefaultIf, EvmYul.Yul.exec] - | cons stmt rest => + simp [nativeSwitchCaseIfs, EvmYul.Yul.exec] + | cons entry rest ih => + rcases entry with ⟨tag, body⟩ have hHead : - EvmYul.Yul.exec (fuel + 7) - (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) + EvmYul.Yul.exec (fuel + rest.length + 9) + (nativeSwitchCaseIf discrName matchedName (tag, body)) codeOverride state = .ok state := by - simpa [nativeSwitchDefaultGuardExpr] using - (exec_if_nativeSwitchDefaultGuard_matched_fuel fuel - (stmt :: rest) codeOverride state matchedName hMatched) + simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using + (exec_if_nativeSwitchGuardedMatch_matched_fuel + (fuel + rest.length) (Backends.lowerAssignNative matchedName (.lit 1) :: body) + codeOverride state discrName matchedName tag hMatched) have hTail : - EvmYul.Yul.exec (fuel + 7) (.Block []) - codeOverride state = .ok state := by - simp [EvmYul.Yul.exec] - simpa [nativeSwitchDefaultIf] using - (exec_block_cons_ok (fuel + 7) - (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) - [] codeOverride state state state hHead hTail) - -/-- Default-tail skip at the fuel level left after a generated case chain. -/ -theorem exec_nativeSwitchDefaultIf_matched_caseTail_fuel - (fuel : Nat) - (defaultBody : List EvmYul.Yul.Ast.Stmt) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state : EvmYul.Yul.State) - (matchedName : EvmYul.Identifier) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 1) : - EvmYul.Yul.exec (fuel + 9) - (.Block (nativeSwitchDefaultIf matchedName defaultBody)) - codeOverride state = .ok state := by - cases defaultBody with - | nil => - simp [nativeSwitchDefaultIf, EvmYul.Yul.exec] - | cons stmt rest => - simpa [nativeSwitchDefaultIf, Nat.add_assoc, Nat.add_comm, - Nat.add_left_comm] using - (exec_nativeSwitchDefaultIf_matched_fuel (fuel + 1) - (stmt :: rest) codeOverride state matchedName hMatched) + EvmYul.Yul.exec (fuel + rest.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName rest)) + codeOverride state = .ok state := + ih fuel codeOverride state discrName matchedName hMatched + have hBlock := exec_block_cons_ok (fuel + rest.length + 9) + (nativeSwitchCaseIf discrName matchedName (tag, body)) + (nativeSwitchCaseIfs discrName matchedName rest) + codeOverride state state state hHead hTail + simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hBlock -/-- Non-empty default-tail execution at the fuel level left after all generated - cases miss. -/ -theorem exec_nativeSwitchDefaultIf_unmatched_caseTail_nonempty_fuel +/-- Whole generated case-chain execution when the first remaining case is the + selected case and suffix cases must skip after the selected body preserves + the matched flag. -/ +theorem exec_nativeSwitchCaseIfs_head_hit_fuel (fuel : Nat) - (defaultBody : List EvmYul.Yul.Ast.Stmt) + (suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) (codeOverride : Option EvmYul.Yul.Ast.YulContract) (state final : EvmYul.Yul.State) - (matchedName : EvmYul.Identifier) + (discrName matchedName : EvmYul.Identifier) (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hDiscr : state[discrName]! = EvmYul.UInt256.ofNat tag) (hBody : - EvmYul.Yul.exec (fuel + 7) (.Block defaultBody) codeOverride state = - .ok final) - (hNonempty : defaultBody ≠ []) : - EvmYul.Yul.exec (fuel + 9) - (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride + (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = .ok final) + (hFinalMatched : final[matchedName]! = EvmYul.UInt256.ofNat 1) : + EvmYul.Yul.exec (fuel + suffix.length + 10) + (.Block + (nativeSwitchCaseIfs discrName matchedName ((tag, body) :: suffix))) codeOverride state = .ok final := by - simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using - (exec_nativeSwitchDefaultIf_unmatched_nonempty_fuel (fuel + 1) - defaultBody codeOverride state final matchedName hMatched hBody hNonempty) + have hHead : + EvmYul.Yul.exec (fuel + suffix.length + 9) + (nativeSwitchCaseIf discrName matchedName (tag, body)) + codeOverride state = .ok final := by + simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using + (exec_if_nativeSwitchGuardedMatch_hit_marked_fuel + (fuel + suffix.length) body codeOverride state final discrName + matchedName tag hMatched hDiscr hBody) + have hTail : + EvmYul.Yul.exec (fuel + suffix.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName suffix)) + codeOverride final = .ok final := + exec_nativeSwitchCaseIfs_matched_fuel fuel suffix codeOverride final + discrName matchedName hFinalMatched + have hBlock := exec_block_cons_ok (fuel + suffix.length + 9) + (nativeSwitchCaseIf discrName matchedName (tag, body)) + (nativeSwitchCaseIfs discrName matchedName suffix) + codeOverride state final final hHead hTail + simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hBlock -/-- Non-empty default-tail error execution at the fuel level left after all - generated cases miss. -/ -theorem exec_nativeSwitchDefaultIf_unmatched_caseTail_nonempty_error_fuel +/-- Whole generated case-chain execution when the first remaining case is the + selected case and that selected body halts or errors before the suffix can + run. -/ +theorem exec_nativeSwitchCaseIfs_head_hit_error_fuel (fuel : Nat) - (defaultBody : List EvmYul.Yul.Ast.Stmt) + (suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) (codeOverride : Option EvmYul.Yul.Ast.YulContract) (state : EvmYul.Yul.State) - (matchedName : EvmYul.Identifier) + (discrName matchedName : EvmYul.Identifier) (err : EvmYul.Yul.Exception) (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hDiscr : state[discrName]! = EvmYul.UInt256.ofNat tag) (hBody : - EvmYul.Yul.exec (fuel + 7) (.Block defaultBody) codeOverride state = - .error err) - (hNonempty : defaultBody ≠ []) : - EvmYul.Yul.exec (fuel + 9) - (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride + (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = .error err) : + EvmYul.Yul.exec (fuel + suffix.length + 10) + (.Block + (nativeSwitchCaseIfs discrName matchedName ((tag, body) :: suffix))) codeOverride state = .error err := by - simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using - (exec_nativeSwitchDefaultIf_unmatched_nonempty_error_fuel (fuel + 1) - defaultBody codeOverride state matchedName err hMatched hBody hNonempty) + have hHead : + EvmYul.Yul.exec (fuel + suffix.length + 9) + (nativeSwitchCaseIf discrName matchedName (tag, body)) + codeOverride state = .error err := by + simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using + (exec_if_nativeSwitchGuardedMatch_hit_marked_error_fuel + (fuel + suffix.length) body codeOverride state discrName matchedName + tag err hMatched hDiscr hBody) + have hBlock := + exec_block_cons_error (fuel + suffix.length + 9) + (nativeSwitchCaseIf discrName matchedName (tag, body)) + (nativeSwitchCaseIfs discrName matchedName suffix) + codeOverride state err hHead + simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hBlock -/-- Compose a generated case chain with its optional default when the case chain - has already set and preserved the matched flag. -/ -theorem exec_nativeSwitchCaseIfs_with_default_matched_fuel +/-- Cons a non-selected generated switch case onto an already-proved generated + case-chain execution. -/ +theorem exec_nativeSwitchCaseIfs_cons_miss_fuel (fuel : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) + (rest : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (missTag : Nat) + (missBody : List EvmYul.Yul.Ast.Stmt) (codeOverride : Option EvmYul.Yul.Ast.YulContract) (state final : EvmYul.Yul.State) (discrName matchedName : EvmYul.Identifier) - (hCases : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .ok final) - (hFinalMatched : final[matchedName]! = EvmYul.UInt256.ofNat 1) : - EvmYul.Yul.exec (fuel + cases.length + 9) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hHeadMiss : state[discrName]! ≠ EvmYul.UInt256.ofNat missTag) + (hTail : + EvmYul.Yul.exec (fuel + rest.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName rest)) + codeOverride state = .ok final) : + EvmYul.Yul.exec (fuel + rest.length + 10) (.Block - (nativeSwitchCaseIfs discrName matchedName cases ++ - nativeSwitchDefaultIf matchedName defaultBody)) + (nativeSwitchCaseIfs discrName matchedName + ((missTag, missBody) :: rest))) codeOverride state = .ok final := by - have hDefault : - EvmYul.Yul.exec (fuel + 9) - (.Block (nativeSwitchDefaultIf matchedName defaultBody)) - codeOverride final = .ok final := - exec_nativeSwitchDefaultIf_matched_caseTail_fuel fuel defaultBody - codeOverride final matchedName hFinalMatched + have hHead : + EvmYul.Yul.exec (fuel + rest.length + 9) + (nativeSwitchCaseIf discrName matchedName (missTag, missBody)) + codeOverride state = .ok state := by + simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using + (exec_if_nativeSwitchGuardedMatch_miss_fuel + (fuel + rest.length) + (Backends.lowerAssignNative matchedName (.lit 1) :: missBody) + codeOverride state discrName matchedName missTag hMatched hHeadMiss) + have hBlock := exec_block_cons_ok (fuel + rest.length + 9) + (nativeSwitchCaseIf discrName matchedName (missTag, missBody)) + (nativeSwitchCaseIfs discrName matchedName rest) + codeOverride state state final hHead hTail simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using exec_block_append_ok fuel 9 - (nativeSwitchCaseIfs discrName matchedName cases) - (nativeSwitchDefaultIf matchedName defaultBody) - codeOverride state final final - (by simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, - Nat.add_left_comm] using hCases) - hDefault + using hBlock -/-- Selector-hit execution for the generated case chain followed by the - generated optional default statement list. The selected body must preserve - the matched flag so the default guard and suffix cases skip. -/ -theorem exec_nativeSwitchCaseIfs_find_hit_with_default_preserved_fuel - (fuel selector : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) +/-- Whole generated case-chain execution for a miss prefix, selected case, and suffix. -/ +theorem exec_nativeSwitchCaseIfs_prefix_hit_fuel + (fuel : Nat) + (pre suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (tag : Nat) (body : List EvmYul.Yul.Ast.Stmt) (codeOverride : Option EvmYul.Yul.Ast.YulContract) (state final : EvmYul.Yul.State) (discrName matchedName : EvmYul.Identifier) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hMarked : (state.insert matchedName (EvmYul.UInt256.ofNat 1))[matchedName]! = - EvmYul.UInt256.ofNat 1) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + (hMissPrefix : ∀ tag' body', (tag', body') ∈ pre → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag') + (hDiscr : state[discrName]! = EvmYul.UInt256.ofNat tag) + (hBody : EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = .ok final) - (hPreservesMatched : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - NativeBlockPreservesWord matchedName (EvmYul.UInt256.ofNat 1) body codeOverride) : - EvmYul.Yul.exec (fuel + cases.length + 9) (.Block - (nativeSwitchCaseIfs discrName matchedName cases ++ nativeSwitchDefaultIf matchedName defaultBody)) + (hFinalMatched : final[matchedName]! = EvmYul.UInt256.ofNat 1) : + EvmYul.Yul.exec (fuel + (pre ++ (tag, body) :: suffix).length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName + (pre ++ (tag, body) :: suffix))) codeOverride state = .ok final := by - have hCases : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .ok final := - exec_nativeSwitchCaseIfs_find_hit_preserved_fuel fuel selector cases tag - body codeOverride state final discrName matchedName hFind hMatched - hDiscrSelector hSelectorRange hTagsRange hMarked hBody hPreservesMatched - have hFinalMatched : final[matchedName]! = EvmYul.UInt256.ofNat 1 := by - rcases nativeSwitch_find_hit_split selector cases tag body hFind with - ⟨pre, suffix, hCasesEq, _hTag, _hPrefix⟩ - exact hPreservesMatched pre suffix hCasesEq - (fuel + suffix.length + 7) - (state.insert matchedName (EvmYul.UInt256.ofNat 1)) final hMarked - (hBody pre suffix hCasesEq) - exact exec_nativeSwitchCaseIfs_with_default_matched_fuel fuel cases - defaultBody codeOverride state final discrName matchedName hCases - hFinalMatched - -/-- Selector-hit execution for the generated case chain followed by the - generated optional default statement list when the selected case halts or - errors. The default never runs because block execution stops at the - selected-case exception. -/ -theorem exec_nativeSwitchCaseIfs_find_hit_with_default_error_fuel - (fuel selector : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (err : EvmYul.Yul.Exception) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride + induction pre generalizing fuel with + | nil => + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_nativeSwitchCaseIfs_head_hit_fuel fuel suffix tag body codeOverride + state final discrName matchedName hMatched hDiscr hBody hFinalMatched) + | cons entry rest ih => + rcases entry with ⟨missTag, missBody⟩ + have hHeadMiss : + state[discrName]! ≠ EvmYul.UInt256.ofNat missTag := by + exact hMissPrefix missTag missBody (by simp) + have hRestMiss : + ∀ tag' body', (tag', body') ∈ rest → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := by + intro tag' body' hmem + exact hMissPrefix tag' body' (by simp [hmem]) + have hTail : + EvmYul.Yul.exec + (fuel + (rest ++ (tag, body) :: suffix).length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName + (rest ++ (tag, body) :: suffix))) + codeOverride state = .ok final := + ih fuel hRestMiss hBody + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_nativeSwitchCaseIfs_cons_miss_fuel fuel + (rest ++ (tag, body) :: suffix) missTag missBody codeOverride state + final discrName matchedName hMatched hHeadMiss hTail) + +/-- Whole generated case-chain execution for a miss prefix, selected case, and + suffix when the selected case halts or errors. -/ +theorem exec_nativeSwitchCaseIfs_prefix_hit_error_fuel + (fuel : Nat) + (pre suffix : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (tag : Nat) (body : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) + (discrName matchedName : EvmYul.Identifier) + (err : EvmYul.Yul.Exception) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hMissPrefix : ∀ tag' body', (tag', body') ∈ pre → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag') + (hDiscr : state[discrName]! = EvmYul.UInt256.ofNat tag) + (hBody : + EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = .error err) : - EvmYul.Yul.exec (fuel + cases.length + 9) (.Block - (nativeSwitchCaseIfs discrName matchedName cases ++ nativeSwitchDefaultIf matchedName defaultBody)) + EvmYul.Yul.exec (fuel + (pre ++ (tag, body) :: suffix).length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName + (pre ++ (tag, body) :: suffix))) codeOverride state = .error err := by - have hCases : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .error err := - exec_nativeSwitchCaseIfs_find_hit_error_fuel fuel selector cases tag body - codeOverride state discrName matchedName err hFind hMatched - hDiscrSelector hSelectorRange hTagsRange hBody - simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using - (exec_block_append_prefix_error fuel 9 - (nativeSwitchCaseIfs discrName matchedName cases) - (nativeSwitchDefaultIf matchedName defaultBody) - codeOverride state err - (by simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, - Nat.add_left_comm] using hCases)) + induction pre generalizing fuel with + | nil => + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_nativeSwitchCaseIfs_head_hit_error_fuel fuel suffix tag body + codeOverride state discrName matchedName err hMatched hDiscr hBody) + | cons entry rest ih => + rcases entry with ⟨missTag, missBody⟩ + have hHeadMiss : + state[discrName]! ≠ EvmYul.UInt256.ofNat missTag := by + exact hMissPrefix missTag missBody (by simp) + have hRestMiss : + ∀ tag' body', (tag', body') ∈ rest → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := by + intro tag' body' hmem + exact hMissPrefix tag' body' (by simp [hmem]) + have hTail : + EvmYul.Yul.exec + (fuel + (rest ++ (tag, body) :: suffix).length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName + (rest ++ (tag, body) :: suffix))) + codeOverride state = .error err := + ih fuel hRestMiss hBody + have hHead : + EvmYul.Yul.exec + (fuel + (rest ++ (tag, body) :: suffix).length + 9) + (nativeSwitchCaseIf discrName matchedName (missTag, missBody)) + codeOverride state = .ok state := by + simpa [nativeSwitchCaseIf, nativeSwitchGuardedMatchExpr] using + (exec_if_nativeSwitchGuardedMatch_miss_fuel + (fuel + (rest ++ (tag, body) :: suffix).length) + (Backends.lowerAssignNative matchedName (.lit 1) :: missBody) + codeOverride state discrName matchedName missTag hMatched hHeadMiss) + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_block_cons_tail_error + (fuel + (rest ++ (tag, body) :: suffix).length + 9) + (nativeSwitchCaseIf discrName matchedName (missTag, missBody)) + (nativeSwitchCaseIfs discrName matchedName + (rest ++ (tag, body) :: suffix)) + codeOverride state state err hHead hTail) -/-- Selector-miss execution for the generated case chain followed by a - non-empty generated default block. -/ -theorem exec_nativeSwitchCaseIfs_find_none_with_default_nonempty_fuel +/-- Whole generated case-chain execution for a selector lookup hit. This wraps + `exec_nativeSwitchCaseIfs_prefix_hit_fuel` with the generated dispatcher + lookup split, so callers only need the `find?` result and the selected body + execution premise for the discovered suffix. -/ +theorem exec_nativeSwitchCaseIfs_find_hit_fuel (fuel selector : Nat) (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) + (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) (codeOverride : Option EvmYul.Yul.Ast.YulContract) (state final : EvmYul.Yul.State) (discrName matchedName : EvmYul.Identifier) - (hFind : - cases.find? (fun entry => entry.1 == selector) = none) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) - (hDefaultBody : - EvmYul.Yul.exec (fuel + 7) (.Block defaultBody) codeOverride state = - .ok final) - (hNonempty : defaultBody ≠ []) : + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : + ∀ pre suffix, + cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) + codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = + .ok final) + (hFinalMatched : final[matchedName]! = EvmYul.UInt256.ofNat 1) : EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block - (nativeSwitchCaseIfs discrName matchedName cases ++ - nativeSwitchDefaultIf matchedName defaultBody)) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) codeOverride state = .ok final := by - have hCases : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .ok state := - exec_nativeSwitchCaseIfs_find_none_fuel fuel selector cases codeOverride - state discrName matchedName hFind hMatched hDiscrSelector hSelectorRange - hTagsRange - have hDefault : - EvmYul.Yul.exec (fuel + 9) - (.Block (nativeSwitchDefaultIf matchedName defaultBody)) - codeOverride state = .ok final := - exec_nativeSwitchDefaultIf_unmatched_caseTail_nonempty_fuel fuel - defaultBody codeOverride state final matchedName hMatched hDefaultBody - hNonempty - simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using - (exec_block_append_ok fuel 9 - (nativeSwitchCaseIfs discrName matchedName cases) - (nativeSwitchDefaultIf matchedName defaultBody) - codeOverride state state final - (by simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, - Nat.add_left_comm] using hCases) - hDefault) + rcases nativeSwitch_find_hit_split selector cases tag body hFind with + ⟨pre, suffix, hCases, hTag, hPrefix⟩ + subst tag + have hMissPrefix : + ∀ tag' body', (tag', body') ∈ pre → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := + nativeSwitch_prefix_miss_of_selector_find selector cases pre suffix selector body + state discrName hCases hPrefix hDiscrSelector hSelectorRange hTagsRange + have hSelectedBody : + EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) + codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = + .ok final := + hBody pre suffix hCases + have hExec := + exec_nativeSwitchCaseIfs_prefix_hit_fuel fuel pre suffix selector body + codeOverride state final discrName matchedName hMatched hMissPrefix + hDiscrSelector hSelectedBody hFinalMatched + simpa [hCases, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hExec -/-- Selector-miss execution for the generated case chain followed by a - non-empty generated default block that halts or errors. -/ -theorem exec_nativeSwitchCaseIfs_find_none_with_default_nonempty_error_fuel +/-- Whole generated case-chain execution for a selector lookup hit whose + selected body halts or errors. -/ +theorem exec_nativeSwitchCaseIfs_find_hit_error_fuel (fuel selector : Nat) (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) + (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) (codeOverride : Option EvmYul.Yul.Ast.YulContract) (state : EvmYul.Yul.State) (discrName matchedName : EvmYul.Identifier) (err : EvmYul.Yul.Exception) - (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) - (hDefaultBody : - EvmYul.Yul.exec (fuel + 7) (.Block defaultBody) codeOverride state = - .error err) - (hNonempty : defaultBody ≠ []) : + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : + ∀ pre suffix, + cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) + codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = + .error err) : EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block - (nativeSwitchCaseIfs discrName matchedName cases ++ - nativeSwitchDefaultIf matchedName defaultBody)) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) codeOverride state = .error err := by - have hCases : - EvmYul.Yul.exec (fuel + cases.length + 9) (.Block - (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .ok state := - exec_nativeSwitchCaseIfs_find_none_fuel fuel selector cases codeOverride - state discrName matchedName hFind hMatched hDiscrSelector hSelectorRange - hTagsRange - have hDefault : - EvmYul.Yul.exec (fuel + 9) (.Block - (nativeSwitchDefaultIf matchedName defaultBody)) - codeOverride state = .error err := - exec_nativeSwitchDefaultIf_unmatched_caseTail_nonempty_error_fuel fuel - defaultBody codeOverride state matchedName err hMatched hDefaultBody - hNonempty - simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using - (exec_block_append_error fuel 9 - (nativeSwitchCaseIfs discrName matchedName cases) - (nativeSwitchDefaultIf matchedName defaultBody) - codeOverride state state err - (by simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, - Nat.add_left_comm] using hCases) - hDefault) + rcases nativeSwitch_find_hit_split selector cases tag body hFind with + ⟨pre, suffix, hCases, hTag, hPrefix⟩ + subst tag + have hMissPrefix : + ∀ tag' body', (tag', body') ∈ pre → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag' := + nativeSwitch_prefix_miss_of_selector_find selector cases pre suffix selector body + state discrName hCases hPrefix hDiscrSelector hSelectorRange hTagsRange + have hSelectedBody : + EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) + codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = + .error err := + hBody pre suffix hCases + have hExec := + exec_nativeSwitchCaseIfs_prefix_hit_error_fuel fuel pre suffix selector body + codeOverride state discrName matchedName err hMatched hMissPrefix + hDiscrSelector hSelectedBody + simpa [hCases, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hExec -/-- Guarded selector-miss execution for the generated lazy switch when the - default body is the compiler's `revert(0, 0)` statement. This discharges the - default-body premise in the generic selector-miss theorem with the actual - native `REVERT` primitive path. -/ -theorem exec_nativeSwitchCaseIfs_find_none_with_revert_default_fuel +/-- Selector-hit case-chain execution with the selected-body matched-flag + preservation obligation factored into a reusable predicate. + +This is the proof boundary needed by the full native dispatcher bridge: the +lowered case body may update storage, memory, and user variables, but it must +not clobber the generated lazy-switch matched flag after the lowering has set +it to one. -/ +theorem exec_nativeSwitchCaseIfs_find_hit_preserved_fuel + (fuel selector : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state final : EvmYul.Yul.State) + (discrName matchedName : EvmYul.Identifier) + (hFind : + cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hMarked : + (state.insert matchedName (EvmYul.UInt256.ofNat 1))[matchedName]! = + EvmYul.UInt256.ofNat 1) + (hBody : + ∀ pre suffix, + cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) + codeOverride (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = + .ok final) + (hPreservesMatched : + ∀ pre suffix, + cases = pre ++ (tag, body) :: suffix → + NativeBlockPreservesWord matchedName (EvmYul.UInt256.ofNat 1) + body codeOverride) : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) + codeOverride state = .ok final := by + apply exec_nativeSwitchCaseIfs_find_hit_fuel + (fuel := fuel) (selector := selector) (cases := cases) (tag := tag) + (body := body) (codeOverride := codeOverride) (state := state) + (final := final) (discrName := discrName) (matchedName := matchedName) + hFind hMatched hDiscrSelector hSelectorRange hTagsRange hBody + rcases nativeSwitch_find_hit_split selector cases tag body hFind with + ⟨pre, suffix, hCases, _hTag, _hPrefix⟩ + exact hPreservesMatched pre suffix hCases (fuel + suffix.length + 7) + (state.insert matchedName (EvmYul.UInt256.ofNat 1)) final hMarked + (hBody pre suffix hCases) + +/-- Whole generated case-chain skip for a selector lookup miss. This packages + the `find? = none` selector fact into the all-cases-miss premise expected by + the lazy native switch executor. -/ +theorem exec_nativeSwitchCaseIfs_find_none_fuel (fuel selector : Nat) (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (codeOverride : Option EvmYul.Yul.Ast.YulContract) @@ -9602,2379 +19871,5182 @@ theorem exec_nativeSwitchCaseIfs_find_none_with_revert_default_fuel (hSelectorRange : selector < EvmYul.UInt256.size) (hTagsRange : ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) + codeOverride state = .ok state := by + have hMiss : + ∀ tag body, (tag, body) ∈ cases → + state[discrName]! ≠ EvmYul.UInt256.ofNat tag := + nativeSwitch_find_none_all_miss selector cases state discrName hFind + hDiscrSelector hSelectorRange hTagsRange + exact exec_nativeSwitchCaseIfs_all_miss_fuel fuel cases codeOverride state + discrName matchedName hMatched hMiss +/-- Non-empty generated default block execution when no case matched. -/ +theorem exec_nativeSwitchDefaultIf_unmatched_nonempty_fuel + (fuel : Nat) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state final : EvmYul.Yul.State) + (matchedName : EvmYul.Identifier) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hBody : + EvmYul.Yul.exec (fuel + 6) (.Block defaultBody) codeOverride state = + .ok final) + (hNonempty : defaultBody ≠ []) : + EvmYul.Yul.exec (fuel + 8) + (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .ok final := by + cases defaultBody with + | nil => contradiction + | cons stmt rest => + have hHead : + EvmYul.Yul.exec (fuel + 7) + (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) + codeOverride state = .ok final := by + simpa [nativeSwitchDefaultGuardExpr] using + (exec_if_nativeSwitchDefaultGuard_unmatched_fuel fuel + (stmt :: rest) codeOverride state final matchedName hMatched hBody) + have hTail : + EvmYul.Yul.exec (fuel + 7) (.Block []) + codeOverride final = .ok final := by + simp [EvmYul.Yul.exec] + exact exec_block_cons_ok (fuel + 7) + (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) + [] codeOverride state final final hHead hTail + +/-- Non-empty generated default block execution when no case matched and the + default body halts or errors. This is the selector-miss path used by a + default `revert(0, 0)` body. -/ +theorem exec_nativeSwitchDefaultIf_unmatched_nonempty_error_fuel + (fuel : Nat) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) + (matchedName : EvmYul.Identifier) + (err : EvmYul.Yul.Exception) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hBody : + EvmYul.Yul.exec (fuel + 6) (.Block defaultBody) codeOverride state = + .error err) + (hNonempty : defaultBody ≠ []) : + EvmYul.Yul.exec (fuel + 8) + (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .error err := by + cases defaultBody with + | nil => contradiction + | cons stmt rest => + have hHead : + EvmYul.Yul.exec (fuel + 7) + (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) + codeOverride state = .error err := by + simpa [nativeSwitchDefaultGuardExpr] using + (exec_if_nativeSwitchDefaultGuard_unmatched_error_fuel fuel + (stmt :: rest) codeOverride state matchedName err hMatched hBody) + exact exec_block_cons_error (fuel + 7) + (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) + [] codeOverride state err hHead + +/-- After a selected case preserves the matched flag at one, the optional + generated default block skips. Empty defaults also skip because no default + statement is emitted. -/ +theorem exec_nativeSwitchDefaultIf_matched_fuel + (fuel : Nat) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) + (matchedName : EvmYul.Identifier) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 1) : + EvmYul.Yul.exec + (fuel + (nativeSwitchDefaultIf matchedName defaultBody).length + 7) + (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .ok state := by + cases defaultBody with + | nil => + simp [nativeSwitchDefaultIf, EvmYul.Yul.exec] + | cons stmt rest => + have hHead : + EvmYul.Yul.exec (fuel + 7) + (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) + codeOverride state = .ok state := by + simpa [nativeSwitchDefaultGuardExpr] using + (exec_if_nativeSwitchDefaultGuard_matched_fuel fuel + (stmt :: rest) codeOverride state matchedName hMatched) + have hTail : + EvmYul.Yul.exec (fuel + 7) (.Block []) + codeOverride state = .ok state := by + simp [EvmYul.Yul.exec] + simpa [nativeSwitchDefaultIf] using + (exec_block_cons_ok (fuel + 7) + (.If (nativeSwitchDefaultGuardExpr matchedName) (stmt :: rest)) + [] codeOverride state state state hHead hTail) + +/-- Default-tail skip at the fuel level left after a generated case chain. -/ +theorem exec_nativeSwitchDefaultIf_matched_caseTail_fuel + (fuel : Nat) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) + (matchedName : EvmYul.Identifier) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 1) : + EvmYul.Yul.exec (fuel + 9) + (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .ok state := by + cases defaultBody with + | nil => + simp [nativeSwitchDefaultIf, EvmYul.Yul.exec] + | cons stmt rest => + simpa [nativeSwitchDefaultIf, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using + (exec_nativeSwitchDefaultIf_matched_fuel (fuel + 1) + (stmt :: rest) codeOverride state matchedName hMatched) + +/-- Non-empty default-tail execution at the fuel level left after all generated + cases miss. -/ +theorem exec_nativeSwitchDefaultIf_unmatched_caseTail_nonempty_fuel + (fuel : Nat) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state final : EvmYul.Yul.State) + (matchedName : EvmYul.Identifier) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hBody : + EvmYul.Yul.exec (fuel + 7) (.Block defaultBody) codeOverride state = + .ok final) + (hNonempty : defaultBody ≠ []) : + EvmYul.Yul.exec (fuel + 9) + (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .ok final := by + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_nativeSwitchDefaultIf_unmatched_nonempty_fuel (fuel + 1) + defaultBody codeOverride state final matchedName hMatched hBody hNonempty) + +/-- Non-empty default-tail error execution at the fuel level left after all + generated cases miss. -/ +theorem exec_nativeSwitchDefaultIf_unmatched_caseTail_nonempty_error_fuel + (fuel : Nat) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) + (matchedName : EvmYul.Identifier) + (err : EvmYul.Yul.Exception) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hBody : + EvmYul.Yul.exec (fuel + 7) (.Block defaultBody) codeOverride state = + .error err) + (hNonempty : defaultBody ≠ []) : + EvmYul.Yul.exec (fuel + 9) + (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .error err := by + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_nativeSwitchDefaultIf_unmatched_nonempty_error_fuel (fuel + 1) + defaultBody codeOverride state matchedName err hMatched hBody hNonempty) + +/-- Compose a generated case chain with its optional default when the case chain + has already set and preserved the matched flag. -/ +theorem exec_nativeSwitchCaseIfs_with_default_matched_fuel + (fuel : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state final : EvmYul.Yul.State) + (discrName matchedName : EvmYul.Identifier) + (hCases : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) + codeOverride state = .ok final) + (hFinalMatched : final[matchedName]! = EvmYul.UInt256.ofNat 1) : EvmYul.Yul.exec (fuel + cases.length + 9) (.Block (nativeSwitchCaseIfs discrName matchedName cases ++ - nativeSwitchDefaultIf matchedName [nativeRevertZeroZeroStmt])) - codeOverride state = .error EvmYul.Yul.Exception.Revert := by - have hDefaultBody : - EvmYul.Yul.exec (fuel + 7) (.Block [nativeRevertZeroZeroStmt]) - codeOverride state = .error EvmYul.Yul.Exception.Revert := by - exact exec_block_cons_error (fuel + 6) nativeRevertZeroZeroStmt [] - codeOverride state EvmYul.Yul.Exception.Revert - (exec_revert_zero_zero_error fuel state codeOverride) - exact exec_nativeSwitchCaseIfs_find_none_with_default_nonempty_error_fuel - fuel selector cases [nativeRevertZeroZeroStmt] codeOverride state - discrName matchedName EvmYul.Yul.Exception.Revert hFind hMatched - hDiscrSelector hSelectorRange hTagsRange hDefaultBody (by simp) + nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .ok final := by + have hDefault : + EvmYul.Yul.exec (fuel + 9) + (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride final = .ok final := + exec_nativeSwitchDefaultIf_matched_caseTail_fuel fuel defaultBody + codeOverride final matchedName hFinalMatched + simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using exec_block_append_ok fuel 9 + (nativeSwitchCaseIfs discrName matchedName cases) + (nativeSwitchDefaultIf matchedName defaultBody) + codeOverride state final final + (by simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hCases) + hDefault + +/-- Selector-hit execution for the generated case chain followed by the + generated optional default statement list. The selected body must preserve + the matched flag so the default guard and suffix cases skip. -/ +theorem exec_nativeSwitchCaseIfs_find_hit_with_default_preserved_fuel + (fuel selector : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state final : EvmYul.Yul.State) + (discrName matchedName : EvmYul.Identifier) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hMarked : (state.insert matchedName (EvmYul.UInt256.ofNat 1))[matchedName]! = + EvmYul.UInt256.ofNat 1) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride + (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = .ok final) + (hPreservesMatched : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + NativeBlockPreservesWord matchedName (EvmYul.UInt256.ofNat 1) body codeOverride) : + EvmYul.Yul.exec (fuel + cases.length + 9) (.Block + (nativeSwitchCaseIfs discrName matchedName cases ++ nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .ok final := by + have hCases : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) + codeOverride state = .ok final := + exec_nativeSwitchCaseIfs_find_hit_preserved_fuel fuel selector cases tag + body codeOverride state final discrName matchedName hFind hMatched + hDiscrSelector hSelectorRange hTagsRange hMarked hBody hPreservesMatched + have hFinalMatched : final[matchedName]! = EvmYul.UInt256.ofNat 1 := by + rcases nativeSwitch_find_hit_split selector cases tag body hFind with + ⟨pre, suffix, hCasesEq, _hTag, _hPrefix⟩ + exact hPreservesMatched pre suffix hCasesEq + (fuel + suffix.length + 7) + (state.insert matchedName (EvmYul.UInt256.ofNat 1)) final hMarked + (hBody pre suffix hCasesEq) + exact exec_nativeSwitchCaseIfs_with_default_matched_fuel fuel cases + defaultBody codeOverride state final discrName matchedName hCases + hFinalMatched + +/-- Selector-hit execution for the generated case chain followed by the + generated optional default statement list when the selected case halts or + errors. The default never runs because block execution stops at the + selected-case exception. -/ +theorem exec_nativeSwitchCaseIfs_find_hit_with_default_error_fuel + (fuel selector : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) + (discrName matchedName : EvmYul.Identifier) + (err : EvmYul.Yul.Exception) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 7) (.Block body) codeOverride + (state.insert matchedName (EvmYul.UInt256.ofNat 1)) = .error err) : + EvmYul.Yul.exec (fuel + cases.length + 9) (.Block + (nativeSwitchCaseIfs discrName matchedName cases ++ nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .error err := by + have hCases : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) + codeOverride state = .error err := + exec_nativeSwitchCaseIfs_find_hit_error_fuel fuel selector cases tag body + codeOverride state discrName matchedName err hFind hMatched + hDiscrSelector hSelectorRange hTagsRange hBody + simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using + (exec_block_append_prefix_error fuel 9 + (nativeSwitchCaseIfs discrName matchedName cases) + (nativeSwitchDefaultIf matchedName defaultBody) + codeOverride state err + (by simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hCases)) + +/-- Selector-miss execution for the generated case chain followed by a + non-empty generated default block. -/ +theorem exec_nativeSwitchCaseIfs_find_none_with_default_nonempty_fuel + (fuel selector : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state final : EvmYul.Yul.State) + (discrName matchedName : EvmYul.Identifier) + (hFind : + cases.find? (fun entry => entry.1 == selector) = none) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) + (hDefaultBody : + EvmYul.Yul.exec (fuel + 7) (.Block defaultBody) codeOverride state = + .ok final) + (hNonempty : defaultBody ≠ []) : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block + (nativeSwitchCaseIfs discrName matchedName cases ++ + nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .ok final := by + have hCases : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) + codeOverride state = .ok state := + exec_nativeSwitchCaseIfs_find_none_fuel fuel selector cases codeOverride + state discrName matchedName hFind hMatched hDiscrSelector hSelectorRange + hTagsRange + have hDefault : + EvmYul.Yul.exec (fuel + 9) + (.Block (nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .ok final := + exec_nativeSwitchDefaultIf_unmatched_caseTail_nonempty_fuel fuel + defaultBody codeOverride state final matchedName hMatched hDefaultBody + hNonempty + simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using + (exec_block_append_ok fuel 9 + (nativeSwitchCaseIfs discrName matchedName cases) + (nativeSwitchDefaultIf matchedName defaultBody) + codeOverride state state final + (by simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hCases) + hDefault) + +/-- Selector-miss execution for the generated case chain followed by a + non-empty generated default block that halts or errors. -/ +theorem exec_nativeSwitchCaseIfs_find_none_with_default_nonempty_error_fuel + (fuel selector : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) + (discrName matchedName : EvmYul.Identifier) + (err : EvmYul.Yul.Exception) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) + (hDefaultBody : + EvmYul.Yul.exec (fuel + 7) (.Block defaultBody) codeOverride state = + .error err) + (hNonempty : defaultBody ≠ []) : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block + (nativeSwitchCaseIfs discrName matchedName cases ++ + nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .error err := by + have hCases : + EvmYul.Yul.exec (fuel + cases.length + 9) (.Block + (nativeSwitchCaseIfs discrName matchedName cases)) + codeOverride state = .ok state := + exec_nativeSwitchCaseIfs_find_none_fuel fuel selector cases codeOverride + state discrName matchedName hFind hMatched hDiscrSelector hSelectorRange + hTagsRange + have hDefault : + EvmYul.Yul.exec (fuel + 9) (.Block + (nativeSwitchDefaultIf matchedName defaultBody)) + codeOverride state = .error err := + exec_nativeSwitchDefaultIf_unmatched_caseTail_nonempty_error_fuel fuel + defaultBody codeOverride state matchedName err hMatched hDefaultBody + hNonempty + simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using + (exec_block_append_error fuel 9 + (nativeSwitchCaseIfs discrName matchedName cases) + (nativeSwitchDefaultIf matchedName defaultBody) + codeOverride state state err + (by simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hCases) + hDefault) + +/-- Guarded selector-miss execution for the generated lazy switch when the + default body is the compiler's `revert(0, 0)` statement. This discharges the + default-body premise in the generic selector-miss theorem with the actual + native `REVERT` primitive path. -/ +theorem exec_nativeSwitchCaseIfs_find_none_with_revert_default_fuel + (fuel selector : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) + (discrName matchedName : EvmYul.Identifier) + (hFind : + cases.find? (fun entry => entry.1 == selector) = none) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block + (nativeSwitchCaseIfs discrName matchedName cases ++ + nativeSwitchDefaultIf matchedName [nativeRevertZeroZeroStmt])) + codeOverride state = .error EvmYul.Yul.Exception.Revert := by + have hDefaultBody : + EvmYul.Yul.exec (fuel + 7) (.Block [nativeRevertZeroZeroStmt]) + codeOverride state = .error EvmYul.Yul.Exception.Revert := by + exact exec_block_cons_error (fuel + 6) nativeRevertZeroZeroStmt [] + codeOverride state EvmYul.Yul.Exception.Revert + (exec_revert_zero_zero_error fuel state codeOverride) + exact exec_nativeSwitchCaseIfs_find_none_with_default_nonempty_error_fuel + fuel selector cases [nativeRevertZeroZeroStmt] codeOverride state + discrName matchedName EvmYul.Yul.Exception.Revert hFind hMatched + hDiscrSelector hSelectorRange hTagsRange hDefaultBody (by simp) + +/-- Selector-miss execution for the generated case chain when no default is + emitted. -/ +theorem exec_nativeSwitchCaseIfs_find_none_without_default_fuel + (fuel selector : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) + (discrName matchedName : EvmYul.Identifier) + (hFind : + cases.find? (fun entry => entry.1 == selector) = none) + (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) + (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block + (nativeSwitchCaseIfs discrName matchedName cases ++ + nativeSwitchDefaultIf matchedName [])) + codeOverride state = .ok state := by + have hCases : + EvmYul.Yul.exec (fuel + cases.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) + codeOverride state = .ok state := + exec_nativeSwitchCaseIfs_find_none_fuel fuel selector cases codeOverride + state discrName matchedName hFind hMatched hDiscrSelector hSelectorRange + hTagsRange + have hDefault : + EvmYul.Yul.exec (fuel + 9) + (.Block (nativeSwitchDefaultIf matchedName [])) + codeOverride state = .ok state := by + simp [nativeSwitchDefaultIf, EvmYul.Yul.exec] + simpa [nativeSwitchCaseIfs, nativeSwitchDefaultIf, Nat.add_assoc, + Nat.add_comm, Nat.add_left_comm] using + (exec_block_append_ok fuel 9 + (nativeSwitchCaseIfs discrName matchedName cases) + (nativeSwitchDefaultIf matchedName []) + codeOverride state state state + (by simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hCases) + hDefault) + +theorem exec_nativeSwitchPrefix_then_tail_fuel + (fuel : Nat) + (tail : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (discrName matchedName : EvmYul.Identifier) + (final : EvmYul.Yul.State) + (hTail : + EvmYul.Yul.exec (fuel + 10) (.Block tail) (some contract) + (nativeSwitchPrefixFinalState contract tx storage observableSlots + discrName matchedName) = + .ok final) : + EvmYul.Yul.exec (fuel + 12) + (.Block (nativeSwitchPrefixStmts discrName matchedName ++ tail)) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .ok final := by + let prefixState := + nativeSwitchPrefixFinalState contract tx storage observableSlots + discrName matchedName + have hPrefix : + EvmYul.Yul.exec (fuel + 12) + (.Block (nativeSwitchPrefixStmts discrName matchedName)) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .ok prefixState := by + simpa [prefixState, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_nativeSwitchPrefix_selector_initialState_ok_fuel fuel + contract tx storage observableSlots discrName matchedName) + exact exec_block_append_ok (fuel + 10) 0 + (nativeSwitchPrefixStmts discrName matchedName) tail + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) + prefixState final + (by simpa [nativeSwitchPrefixStmts, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hPrefix) + (by simpa [prefixState] using hTail) + +theorem exec_nativeSwitchPrefix_then_tail_error_fuel + (fuel : Nat) + (tail : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (discrName matchedName : EvmYul.Identifier) + (err : EvmYul.Yul.Exception) + (hTail : + EvmYul.Yul.exec (fuel + 10) (.Block tail) (some contract) + (nativeSwitchPrefixFinalState contract tx storage observableSlots + discrName matchedName) = + .error err) : + EvmYul.Yul.exec (fuel + 12) + (.Block (nativeSwitchPrefixStmts discrName matchedName ++ tail)) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .error err := by + let prefixState := + nativeSwitchPrefixFinalState contract tx storage observableSlots + discrName matchedName + have hPrefix : + EvmYul.Yul.exec (fuel + 12) + (.Block (nativeSwitchPrefixStmts discrName matchedName)) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .ok prefixState := by + simpa [prefixState, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + (exec_nativeSwitchPrefix_selector_initialState_ok_fuel fuel + contract tx storage observableSlots discrName matchedName) + exact exec_block_append_error (fuel + 10) 0 + (nativeSwitchPrefixStmts discrName matchedName) tail + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) + prefixState err + (by simpa [nativeSwitchPrefixStmts, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hPrefix) + (by simpa [prefixState] using hTail) + +theorem exec_nativeSwitchTail_find_hit_preserved_fuel + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (final : EvmYul.Yul.State) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchMarkedPrefixStateForId contract tx storage observableSlots switchId) = .ok final) + (hPreservesMatched : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) body (some contract)) : + EvmYul.Yul.exec (fuel + cases.length + 10) + (.Block (nativeSwitchTailStmts switchId cases defaultBody)) + (some contract) (nativeSwitchPrefixStateForId contract tx storage observableSlots switchId) = + .ok final := by + let discrName : EvmYul.Identifier := Backends.nativeSwitchDiscrTempName switchId + let matchedName : EvmYul.Identifier := Backends.nativeSwitchMatchedTempName switchId + let prefixState := + nativeSwitchPrefixFinalState contract tx storage observableSlots + discrName matchedName + have hCasesDefault := + exec_nativeSwitchCaseIfs_find_hit_with_default_preserved_fuel + (fuel + 1) selector cases defaultBody tag body (some contract) + prefixState final discrName matchedName hFind + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_matched contract tx storage + observableSlots discrName matchedName)) + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_discr contract tx storage observableSlots + discrName matchedName selector + (nativeSwitchDiscrTempName_ne_matchedTempName switchId) hSelector)) + hSelectorRange hTagsRange + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_marked contract tx storage + observableSlots discrName matchedName)) + (by intro pre suffix hCases; simpa [nativeSwitchMarkedPrefixStateForId, + nativeSwitchPrefixStateForId, prefixState, discrName, matchedName] + using hBody pre suffix hCases) + (by intro pre suffix hCases; simpa [matchedName] using + hPreservesMatched pre suffix hCases) + simpa [nativeSwitchTailStmts, nativeSwitchPrefixStateForId, prefixState, + discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hCasesDefault + +/-- Selector-hit switch-tail execution deriving matched-flag preservation from generated freshness. -/ +theorem exec_nativeSwitchTail_find_hit_fresh_fuel + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (final : EvmYul.Yul.State) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchMarkedPrefixStateForId contract tx storage observableSlots switchId) = .ok final) + (hStmtPreserves : + ∀ stmt, stmt ∈ body → + Backends.nativeSwitchMatchedTempName switchId ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) : + EvmYul.Yul.exec (fuel + cases.length + 10) + (.Block (nativeSwitchTailStmts switchId cases defaultBody)) + (some contract) (nativeSwitchPrefixStateForId contract tx storage observableSlots switchId) = + .ok final := by + apply exec_nativeSwitchTail_find_hit_preserved_fuel fuel selector switchId tag + cases defaultBody body contract tx storage observableSlots final hSelector + hFind hSelectorRange hTagsRange hBody + intro pre suffix _hCases + exact NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + switchId selector tag body defaultBody cases (EvmYul.UInt256.ofNat 1) + (some contract) hFresh hFind hStmtPreserves + +theorem exec_nativeSwitchTail_find_hit_error_fuel + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchMarkedPrefixStateForId contract tx storage observableSlots switchId) = .error err) : + EvmYul.Yul.exec (fuel + cases.length + 10) + (.Block (nativeSwitchTailStmts switchId cases defaultBody)) + (some contract) (nativeSwitchPrefixStateForId contract tx storage observableSlots switchId) = + .error err := by + let discrName : EvmYul.Identifier := Backends.nativeSwitchDiscrTempName switchId + let matchedName : EvmYul.Identifier := Backends.nativeSwitchMatchedTempName switchId + let prefixState := + nativeSwitchPrefixFinalState contract tx storage observableSlots + discrName matchedName + have hCasesDefault := + exec_nativeSwitchCaseIfs_find_hit_with_default_error_fuel + (fuel + 1) selector cases defaultBody tag body (some contract) + prefixState discrName matchedName err hFind + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_matched contract tx storage + observableSlots discrName matchedName)) + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_discr contract tx storage observableSlots + discrName matchedName selector + (nativeSwitchDiscrTempName_ne_matchedTempName switchId) hSelector)) + hSelectorRange hTagsRange + (by intro pre suffix hCases; simpa [nativeSwitchMarkedPrefixStateForId, + nativeSwitchPrefixStateForId, prefixState, discrName, matchedName] + using hBody pre suffix hCases) + simpa [nativeSwitchTailStmts, nativeSwitchPrefixStateForId, prefixState, + discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hCasesDefault + +theorem exec_nativeSwitchTail_find_none_with_default_nonempty_fuel + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (final : EvmYul.Yul.State) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) + (hDefaultBody : + EvmYul.Yul.exec ((fuel + 1) + 7) (.Block defaultBody) (some contract) + (nativeSwitchPrefixStateForId contract tx storage observableSlots + switchId) = .ok final) + (hNonempty : defaultBody ≠ []) : + EvmYul.Yul.exec (fuel + cases.length + 10) + (.Block (nativeSwitchTailStmts switchId cases defaultBody)) + (some contract) (nativeSwitchPrefixStateForId contract tx storage + observableSlots switchId) = + .ok final := by + let discrName : EvmYul.Identifier := Backends.nativeSwitchDiscrTempName switchId + let matchedName : EvmYul.Identifier := Backends.nativeSwitchMatchedTempName switchId + let prefixState := + nativeSwitchPrefixFinalState contract tx storage observableSlots + discrName matchedName + have hCasesDefault := + exec_nativeSwitchCaseIfs_find_none_with_default_nonempty_fuel + (fuel + 1) selector cases defaultBody (some contract) + prefixState final discrName matchedName hFind + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_matched contract tx storage + observableSlots discrName matchedName)) + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_discr contract tx storage observableSlots + discrName matchedName selector + (nativeSwitchDiscrTempName_ne_matchedTempName switchId) hSelector)) + hSelectorRange hTagsRange + (by simpa [nativeSwitchPrefixStateForId, prefixState, discrName, + matchedName] using hDefaultBody) + hNonempty + simpa [nativeSwitchTailStmts, nativeSwitchPrefixStateForId, prefixState, + discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hCasesDefault + +theorem exec_nativeSwitchTail_find_none_without_default_fuel + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 10) + (.Block (nativeSwitchTailStmts switchId cases [])) + (some contract) (nativeSwitchPrefixStateForId contract tx storage + observableSlots switchId) = + .ok (nativeSwitchPrefixStateForId contract tx storage observableSlots + switchId) := by + let discrName : EvmYul.Identifier := Backends.nativeSwitchDiscrTempName switchId + let matchedName : EvmYul.Identifier := Backends.nativeSwitchMatchedTempName switchId + let prefixState := + nativeSwitchPrefixFinalState contract tx storage observableSlots + discrName matchedName + have hCasesDefault := + exec_nativeSwitchCaseIfs_find_none_without_default_fuel + (fuel + 1) selector cases (some contract) + prefixState discrName matchedName hFind + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_matched contract tx storage + observableSlots discrName matchedName)) + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_discr contract tx storage observableSlots + discrName matchedName selector + (nativeSwitchDiscrTempName_ne_matchedTempName switchId) hSelector)) + hSelectorRange hTagsRange + simpa [nativeSwitchTailStmts, nativeSwitchPrefixStateForId, prefixState, + discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hCasesDefault + +/-- Selector-miss execution for a lowered switch tail with the compiler's + generated `revert(0, 0)` default. This carries the guarded miss proof from + the case-chain level to the switch-tail shape used by lowered dispatchers. -/ +theorem exec_nativeSwitchTail_find_none_with_revert_default_fuel + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 10) + (.Block (nativeSwitchTailStmts switchId cases [nativeRevertZeroZeroStmt])) + (some contract) (nativeSwitchPrefixStateForId contract tx storage + observableSlots switchId) = + .error EvmYul.Yul.Exception.Revert := by + let discrName : EvmYul.Identifier := Backends.nativeSwitchDiscrTempName switchId + let matchedName : EvmYul.Identifier := Backends.nativeSwitchMatchedTempName switchId + let prefixState := + nativeSwitchPrefixFinalState contract tx storage observableSlots + discrName matchedName + have hCasesDefault := + exec_nativeSwitchCaseIfs_find_none_with_revert_default_fuel + (fuel + 1) selector cases (some contract) + prefixState discrName matchedName hFind + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_matched contract tx storage + observableSlots discrName matchedName)) + (by simpa [prefixState, discrName, matchedName] using + (nativeSwitchPrefixFinalState_discr contract tx storage observableSlots + discrName matchedName selector + (nativeSwitchDiscrTempName_ne_matchedTempName switchId) hSelector)) + hSelectorRange hTagsRange + simpa [nativeSwitchTailStmts, nativeSwitchPrefixStateForId, prefixState, + discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hCasesDefault + +theorem exec_lowerNativeSwitchBlock_selector_find_hit_preserved_fuel + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (final : EvmYul.Yul.State) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) + ((nativeSwitchPrefixFinalState contract tx storage observableSlots + (Backends.nativeSwitchDiscrTempName switchId) + (Backends.nativeSwitchMatchedTempName switchId)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) = .ok final) + (hPreservesMatched : ∀ pre suffix, + cases = pre ++ (tag, body) :: suffix → + NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) body (some contract)) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .ok final := by + rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] + apply exec_nativeSwitchPrefix_then_tail_fuel + exact exec_nativeSwitchTail_find_hit_preserved_fuel fuel selector switchId tag + cases defaultBody body contract tx storage observableSlots final + hSelector hFind hSelectorRange hTagsRange hBody hPreservesMatched + +theorem exec_lowerNativeSwitchBlock_selector_find_hit_fresh_fuel + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (final : EvmYul.Yul.State) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) + ((nativeSwitchPrefixFinalState contract tx storage observableSlots + (Backends.nativeSwitchDiscrTempName switchId) + (Backends.nativeSwitchMatchedTempName switchId)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) = .ok final) + (hStmtPreserves : + ∀ stmt, stmt ∈ body → + Backends.nativeSwitchMatchedTempName switchId ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .ok final := by + rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] + apply exec_nativeSwitchPrefix_then_tail_fuel + exact exec_nativeSwitchTail_find_hit_fresh_fuel fuel selector switchId tag + cases defaultBody body contract tx storage observableSlots final hSelector + hFind hSelectorRange hTagsRange hFresh hBody hStmtPreserves + +theorem exec_lowerNativeSwitchBlock_selector_find_hit_error_fuel + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) + ((nativeSwitchPrefixFinalState contract tx storage observableSlots + (Backends.nativeSwitchDiscrTempName switchId) + (Backends.nativeSwitchMatchedTempName switchId)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) = .error err) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .error err := by + rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] + apply exec_nativeSwitchPrefix_then_tail_error_fuel + exact exec_nativeSwitchTail_find_hit_error_fuel fuel selector switchId tag + cases defaultBody body contract tx storage observableSlots err + hSelector hFind hSelectorRange hTagsRange hBody + +theorem exec_lowerNativeSwitchBlock_selector_find_none_with_default_nonempty_fuel + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (final : EvmYul.Yul.State) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) + (hDefaultBody : + EvmYul.Yul.exec ((fuel + 1) + 7) (.Block defaultBody) (some contract) + (nativeSwitchPrefixFinalState contract tx storage observableSlots + (Backends.nativeSwitchDiscrTempName switchId) + (Backends.nativeSwitchMatchedTempName switchId)) = + .ok final) + (hNonempty : defaultBody ≠ []) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .ok final := by + rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] + apply exec_nativeSwitchPrefix_then_tail_fuel + exact exec_nativeSwitchTail_find_none_with_default_nonempty_fuel fuel + selector switchId cases defaultBody contract tx storage observableSlots + final hSelector hFind hSelectorRange hTagsRange hDefaultBody hNonempty + +/-- Guarded selector-miss execution for a fully lowered native switch block + whose generated default is `revert(0, 0)`. This discharges the generic + default-body premise with the actual native `REVERT` primitive path at the + same lowered-block boundary used by dispatcher proofs. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_fuel + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + [nativeRevertZeroZeroStmt]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .error EvmYul.Yul.Exception.Revert := by + rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] + apply exec_nativeSwitchPrefix_then_tail_error_fuel + exact exec_nativeSwitchTail_find_none_with_revert_default_fuel fuel selector + switchId cases contract tx storage observableSlots hSelector hFind + hSelectorRange hTagsRange + +/-- Store-parametric prefix-then-tail-error glue for `lowerNativeSwitchBlock`. + Given the tail body errors on the post-prefix state extended over an + arbitrary preceding native varstore, the full lowered switch block errors + on the matching state with that store. Together with the store-parametric + prefix lemma `exec_nativeSwitchPrefix_selector_initialState_store_ok_fuel`, + this lifts switch-block error proofs to states already carrying additional + bindings (e.g. the buildSwitch wrapper's `__has_selector := 1`). -/ +theorem exec_lowerNativeSwitchBlock_storePrefix_tail_error_fuel + (fuel switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (err : EvmYul.Yul.Exception) + (hTail : + EvmYul.Yul.exec (fuel + 10) + (.Block (nativeSwitchTailStmts switchId cases defaultBody)) + (some contract) + (((.Ok (initialState contract tx storage observableSlots).sharedState store + : EvmYul.Yul.State).insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)) = + .error err) : + EvmYul.Yul.exec (fuel + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (.Ok (initialState contract tx storage observableSlots).sharedState store) = + .error err := by + let discrName := Backends.nativeSwitchDiscrTempName switchId + let matchedName := Backends.nativeSwitchMatchedTempName switchId + let initState : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + let prefixState : EvmYul.Yul.State := + (initState.insert discrName + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + matchedName (EvmYul.UInt256.ofNat 0) + rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] + apply exec_block_append_error (fuel + 10) 0 + (nativeSwitchPrefixStmts discrName matchedName) + (nativeSwitchTailStmts switchId cases defaultBody) + (some contract) initState prefixState err + · simpa [nativeSwitchPrefixStmts, prefixState, initState, Nat.add_assoc, + Nat.add_comm, Nat.add_left_comm] using + exec_nativeSwitchPrefix_selector_initialState_store_ok_fuel + fuel contract tx storage observableSlots store discrName matchedName + · simpa [prefixState, initState] using hTail + +def nativeSwitchStoreInitialState + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + +def nativeSwitchStorePrefixStateForId + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (switchId : Nat) (store : EvmYul.Yul.VarStore) : EvmYul.Yul.State := + ((nativeSwitchStoreInitialState contract tx storage observableSlots store).insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) (EvmYul.UInt256.ofNat 0) + +def nativeSwitchStoreMarkedPrefixStateForId + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (switchId : Nat) (store : EvmYul.Yul.VarStore) : EvmYul.Yul.State := + (nativeSwitchStorePrefixStateForId contract tx storage observableSlots + switchId store).insert + (Backends.nativeSwitchMatchedTempName switchId) (EvmYul.UInt256.ofNat 1) + +theorem nativeSwitchStoreMarkedPrefixStateForId_reviveJump_eq + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (switchId : Nat) (store : EvmYul.Yul.VarStore) : + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage observableSlots + switchId store).reviveJump = + nativeSwitchStoreMarkedPrefixStateForId contract tx storage observableSlots + switchId store := by + simp [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert, EvmYul.Yul.State.reviveJump] + +@[simp] theorem nativeSwitchStoreMarkedPrefixStateForId_weiValue + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (switchId : Nat) (store : EvmYul.Yul.VarStore) : + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage observableSlots + switchId store).sharedState.executionEnv.weiValue = + natToUInt256 tx.msgValue := by + simp [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.insert, + YulState.initial, toSharedState, mkBlockHeader] + +@[simp] theorem nativeSwitchStoreMarkedPrefixStateForId_calldata_size + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (switchId : Nat) (store : EvmYul.Yul.VarStore) : + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage observableSlots + switchId store).sharedState.executionEnv.calldata.size = + 4 + tx.args.length * 32 := by + simp [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.insert, + YulState.initial, toSharedState, mkBlockHeader, calldataToByteArray_size] + +@[simp] theorem nativeSwitchStoreMarkedPrefixStateForId_matched + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (switchId : Nat) (store : EvmYul.Yul.VarStore) : + ∀ matchedName : EvmYul.Identifier, + matchedName = Backends.nativeSwitchMatchedTempName switchId → + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store)[matchedName]! = + EvmYul.UInt256.ofNat 1 := by + intro matchedName hMatchedName + subst matchedName + simpa [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState] using + state_getElem_insert_self_ok + (initialState contract tx storage observableSlots).sharedState + ((store.insert (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)) + (Backends.nativeSwitchMatchedTempName switchId) (EvmYul.UInt256.ofNat 1) + +/-- Selected-switch-state form of the callvalue guard skip: after the lazy +switch has selected a function case and marked the matched flag, a modular-zero +`msgValue` still skips the generated native callvalue revert guard. -/ +theorem exec_if_callvalue_skip_markedPrefix_zero_mod_fuel + (fuel : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hZero : tx.msgValue % evmModulus = 0) : + EvmYul.Yul.exec (fuel + 6) + (.If (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) body) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) = + .ok (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) := by + have hWei : + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store).sharedState.executionEnv.weiValue = + (⟨0⟩ : EvmYul.Literal) := by + rw [nativeSwitchStoreMarkedPrefixStateForId_weiValue] + exact natToUInt256_eq_zero_of_mod_evm tx.msgValue hZero + simpa [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert] using + exec_if_lowerExprNative_callvalue_skip_zero_fuel fuel body (some contract) + (initialState contract tx storage observableSlots).sharedState + (((store.insert (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + hWei + +/-- Selected-switch-state form of the callvalue guard failure: after the lazy +switch has selected a non-payable function case and the transaction has +nonzero modular `msgValue`, the generated native `callvalue()` guard executes +its `revert(0, 0)` body and returns a native revert error. -/ +theorem exec_if_callvalue_take_markedPrefix_nonzero_revert_fuel + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hNonzero : tx.msgValue % evmModulus ≠ 0) : + EvmYul.Yul.exec (fuel + 8) + (.If (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + [nativeRevertZeroZeroStmt]) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) = + .error EvmYul.Yul.Exception.Revert := by + let state := + nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store + have hEval : + EvmYul.Yul.eval (fuel + 7) + (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + (some contract) state = + .ok (state, natToUInt256 tx.msgValue) := by + simpa [state] using + (eval_lowerExprNative_callvalue_ok_fuel (fuel + 2) + (state.sharedState) (state.store) (some contract)) + have hBody : + EvmYul.Yul.exec (fuel + 7) (.Block [nativeRevertZeroZeroStmt]) + (some contract) state = + .error EvmYul.Yul.Exception.Revert := by + have hFuel : fuel + 7 = Nat.succ (fuel + 6) := by omega + rw [hFuel] + exact exec_block_cons_error (fuel + 6) nativeRevertZeroZeroStmt [] + (some contract) state EvmYul.Yul.Exception.Revert + (exec_revert_zero_zero_error fuel state (some contract)) + have hFuel : fuel + 8 = Nat.succ (fuel + 7) := by omega + rw [hFuel] + exact exec_if_eval_nonzero_error (fuel + 7) + (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + [nativeRevertZeroZeroStmt] (some contract) state state + (natToUInt256 tx.msgValue) EvmYul.Yul.Exception.Revert + hEval (natToUInt256_ne_zero_of_mod_ne tx.msgValue hNonzero) hBody + +/-- Selected-switch-state form of the calldata-size guard skip: after the lazy +switch has selected a function case and marked the matched flag, the generated +`lt(calldatasize(), k)` revert guard skips whenever the current calldata size +is at least `k`. -/ +theorem exec_if_lt_calldatasize_skip_markedPrefix_ge_fuel + (fuel : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (k : Nat) + (hSize : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hKSize : k < EvmYul.UInt256.size) + (hGe : k ≤ 4 + tx.args.length * 32) : + EvmYul.Yul.exec (fuel + 9) + (.If (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit k])) + body) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) = + .ok (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) := by + have hSize' : + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store).sharedState.executionEnv.calldata.size < + EvmYul.UInt256.size := by + simpa using hSize + have hGe' : + k ≤ + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store).sharedState.executionEnv.calldata.size := by + simpa using hGe + simpa [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert] using + exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel fuel body + (some contract) + (initialState contract tx storage observableSlots).sharedState + (((store.insert (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + k hSize' hKSize hGe' + +/-- Selected-switch-state form of the calldata-size guard take: after the lazy +switch has selected a function case and marked the matched flag, the generated +`lt(calldatasize(), k)` revert guard executes `revert(0, 0)` whenever the +current calldata size is less than `k`. -/ +theorem exec_if_lt_calldatasize_take_markedPrefix_lt_revert_fuel + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (k : Nat) + (hSize : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hKSize : k < EvmYul.UInt256.size) + (hLt : 4 + tx.args.length * 32 < k) : + EvmYul.Yul.exec (fuel + 9) + (.If (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], + Yul.YulExpr.lit k])) + [nativeRevertZeroZeroStmt]) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) = + .error EvmYul.Yul.Exception.Revert := by + have hSize' : + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store).sharedState.executionEnv.calldata.size < + EvmYul.UInt256.size := by + simpa using hSize + have hLt' : + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store).sharedState.executionEnv.calldata.size < + k := by + simpa using hLt + simpa [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert] using + exec_if_lowerExprNative_lt_calldatasize_take_lt_revert_fuel fuel + (some contract) + (initialState contract tx storage observableSlots).sharedState + (((store.insert (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) + k hSize' hKSize hLt' + +/-- Execute a payable selected switch-case prefix as a no-op and continue with +the lowered user body. The generated case prefix is the lowered comment no-op +followed by the calldata-size revert guard. -/ +theorem exec_switchCaseBody_payable_prefix_eq + (fuel : Nat) + (guardBody bodyNative : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (k : Nat) + (hSize : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hKSize : k < EvmYul.UInt256.size) + (hGe : k ≤ 4 + tx.args.length * 32) : + EvmYul.Yul.exec (fuel + 11) + (.Block + (EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit k])) + guardBody :: + bodyNative)) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) = + EvmYul.Yul.exec (fuel + 9) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) := by + have hFuel : fuel + 11 = Nat.succ (Nat.succ (fuel + 9)) := by omega + rw [hFuel] + rw [exec_block_noop_block_head_eq] + apply exec_block_cons_ok_eq (fuel + 9) + exact exec_if_lt_calldatasize_skip_markedPrefix_ge_fuel fuel guardBody + contract tx storage observableSlots switchId store k hSize hKSize hGe + +/-- Execute a payable selected switch-case prefix through the failing +calldata-size guard. The generated label no-op is skipped, then the concrete +`lt(calldatasize(), k)` guard runs its `revert(0, 0)` body before any user +body statements execute. -/ +theorem exec_switchCaseBody_payable_calldata_revert_fuel + (fuel : Nat) + (bodyNative : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (k : Nat) + (hSize : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hKSize : k < EvmYul.UInt256.size) + (hLt : 4 + tx.args.length * 32 < k) : + EvmYul.Yul.exec (fuel + 11) + (.Block + (EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit k])) + [nativeRevertZeroZeroStmt] :: + bodyNative)) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) = + .error EvmYul.Yul.Exception.Revert := by + have hFuel : fuel + 11 = Nat.succ (Nat.succ (fuel + 9)) := by omega + rw [hFuel] + rw [exec_block_noop_block_head_eq] + apply exec_block_cons_error (fuel + 9) + exact exec_if_lt_calldatasize_take_markedPrefix_lt_revert_fuel fuel + contract tx storage observableSlots switchId store k hSize hKSize hLt + +/-- Execute a non-payable selected switch-case prefix as no-ops and continue +with the lowered user body. The generated case prefix is the lowered comment +no-op, the callvalue revert guard, and then the calldata-size revert guard. -/ +theorem exec_switchCaseBody_nonpayable_prefix_eq + (fuel : Nat) + (callvalueGuardBody calldataGuardBody bodyNative : + List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (k : Nat) + (hZero : tx.msgValue % evmModulus = 0) + (hSize : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hKSize : k < EvmYul.UInt256.size) + (hGe : k ≤ 4 + tx.args.length * 32) : + EvmYul.Yul.exec (fuel + 12) + (.Block + (EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + callvalueGuardBody :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit k])) + calldataGuardBody :: + bodyNative)) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) = + EvmYul.Yul.exec (fuel + 9) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) := by + have hFuel : fuel + 12 = Nat.succ (Nat.succ (fuel + 10)) := by omega + rw [hFuel] + rw [exec_block_noop_block_head_eq] + calc + EvmYul.Yul.exec (Nat.succ (fuel + 10)) + (.Block + (EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + callvalueGuardBody :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit k])) + calldataGuardBody :: + bodyNative)) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) + = + EvmYul.Yul.exec (fuel + 10) + (.Block + (EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit k])) + calldataGuardBody :: + bodyNative)) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) := by + apply exec_block_cons_ok_eq (fuel + 10) + exact exec_if_callvalue_skip_markedPrefix_zero_mod_fuel (fuel + 4) + callvalueGuardBody contract tx storage observableSlots switchId + store hZero + _ = EvmYul.Yul.exec (fuel + 9) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) := by + have hTailFuel : fuel + 10 = Nat.succ (fuel + 9) := by omega + rw [hTailFuel] + apply exec_block_cons_ok_eq (fuel + 9) + exact exec_if_lt_calldatasize_skip_markedPrefix_ge_fuel fuel + calldataGuardBody contract tx storage observableSlots switchId + store k hSize hKSize hGe + +/-- Execute a non-payable selected switch-case prefix through the failing +callvalue guard. The generated label no-op is skipped, then the concrete +`callvalue()` guard runs its `revert(0, 0)` body before any calldata guard or +user body statements execute. -/ +theorem exec_switchCaseBody_nonpayable_callvalue_revert_fuel + (fuel : Nat) + (calldataGuardBody bodyNative : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (k : Nat) + (hNonzero : tx.msgValue % evmModulus ≠ 0) : + EvmYul.Yul.exec (fuel + 12) + (.Block + (EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + [nativeRevertZeroZeroStmt] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit k])) + calldataGuardBody :: + bodyNative)) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) = + .error EvmYul.Yul.Exception.Revert := by + have hFuel : fuel + 12 = Nat.succ (Nat.succ (fuel + 10)) := by omega + rw [hFuel] + rw [exec_block_noop_block_head_eq] + apply exec_block_cons_error (fuel + 10) + exact exec_if_callvalue_take_markedPrefix_nonzero_revert_fuel (fuel + 2) + contract tx storage observableSlots switchId store hNonzero + +/-- Execute a non-payable selected switch-case prefix through the failing +calldata-size guard after the zero-callvalue guard skips. -/ +theorem exec_switchCaseBody_nonpayable_calldata_revert_fuel + (fuel : Nat) + (bodyNative : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (k : Nat) + (hZero : tx.msgValue % evmModulus = 0) + (hSize : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hKSize : k < EvmYul.UInt256.size) + (hLt : 4 + tx.args.length * 32 < k) : + EvmYul.Yul.exec (fuel + 12) + (.Block + (EvmYul.Yul.Ast.Stmt.Block [] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + [nativeRevertZeroZeroStmt] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit k])) + [nativeRevertZeroZeroStmt] :: + bodyNative)) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) = + .error EvmYul.Yul.Exception.Revert := by + have hFuel : fuel + 12 = Nat.succ (Nat.succ (fuel + 10)) := by omega + rw [hFuel] + rw [exec_block_noop_block_head_eq] + calc + EvmYul.Yul.exec (Nat.succ (fuel + 10)) + (.Block + (EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (Yul.YulExpr.call "callvalue" [])) + [nativeRevertZeroZeroStmt] :: + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit k])) + [nativeRevertZeroZeroStmt] :: + bodyNative)) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) + = + EvmYul.Yul.exec (fuel + 10) + (.Block + (EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (Yul.YulExpr.call "lt" + [Yul.YulExpr.call "calldatasize" [], Yul.YulExpr.lit k])) + [nativeRevertZeroZeroStmt] :: + bodyNative)) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) := by + apply exec_block_cons_ok_eq (fuel + 10) + exact exec_if_callvalue_skip_markedPrefix_zero_mod_fuel (fuel + 4) + [nativeRevertZeroZeroStmt] contract tx storage observableSlots + switchId store hZero + _ = .error EvmYul.Yul.Exception.Revert := by + have hTailFuel : fuel + 10 = Nat.succ (fuel + 9) := by omega + rw [hTailFuel] + apply exec_block_cons_error (fuel + 9) + exact exec_if_lt_calldatasize_take_markedPrefix_lt_revert_fuel fuel + contract tx storage observableSlots switchId store k hSize hKSize + hLt + +/-- Lowering-aware payable generated-case prefix peel. Starting from the actual +native lowering result of `switchCaseBody fn`, expose the lowered user body and +normalize execution of the generated comment/calldata guards to that body. -/ +theorem exec_switchCaseBody_payable_lowered_prefix_eq + (fuel : Nat) + (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) + (body' : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (body', next)) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) ∧ + EvmYul.Yul.exec (fuel + 11) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId store) = + EvmYul.Yul.exec (fuel + 9) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId store) := by + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames n0 fn body' next hPayable hLower with + ⟨guardBody, bodyNative, bodyStart, hBodyShape, hBodyLower⟩ + refine ⟨bodyNative, bodyStart, hBodyLower, ?_⟩ + rw [hBodyShape] + exact exec_switchCaseBody_payable_prefix_eq fuel guardBody bodyNative + contract (YulTransaction.ofIR tx) storage observableSlots switchId store + (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + (by simp; omega) + +/-- Lowering-aware non-payable generated-case prefix peel. Starting from the +actual native lowering result of `switchCaseBody fn`, expose the lowered user +body and normalize execution of the generated comment/callvalue/calldata guards +to that body. -/ +theorem exec_switchCaseBody_nonpayable_lowered_prefix_eq + (fuel : Nat) + (reservedNames : List String) (n0 : Nat) + (fn : IRFunction) + (body' : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (body', next)) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) ∧ + EvmYul.Yul.exec (fuel + 12) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId store) = + EvmYul.Yul.exec (fuel + 9) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId store) := by + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames n0 fn body' next hNonPayable hLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, bodyStart, + hBodyShape, hBodyLower⟩ + refine ⟨bodyNative, bodyStart, hBodyLower, ?_⟩ + rw [hBodyShape] + exact exec_switchCaseBody_nonpayable_prefix_eq fuel callvalueGuardBody + calldataGuardBody bodyNative contract (YulTransaction.ofIR tx) storage + observableSlots switchId store (4 + fn.params.length * 32) + (DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable fn tx hguards + hNonPayable) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + (by simp; omega) + +def nativeSwitchHasSelectorStore : EvmYul.Yul.VarStore := + (∅ : EvmYul.Yul.VarStore).insert "__has_selector" (EvmYul.UInt256.ofNat 1) + +def nativeSwitchHasSelectorInitialState + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) : EvmYul.Yul.State := + nativeSwitchStoreInitialState contract tx storage observableSlots + nativeSwitchHasSelectorStore + +theorem nativeSwitchInitialOkState_insert_hasSelector_eq + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) : + (nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1) = + nativeSwitchHasSelectorInitialState contract tx storage observableSlots := by + simp [nativeSwitchInitialOkState, nativeSwitchHasSelectorInitialState, + nativeSwitchStoreInitialState, nativeSwitchHasSelectorStore, + EvmYul.Yul.State.insert] + +/-- `matched := 0` lookup on the post-prefix state with arbitrary store. -/ +theorem nativeSwitchPrefixStoreState_matched_eq + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (discrName matchedName : EvmYul.Identifier) + (discrValue : EvmYul.Literal) : + (((.Ok (initialState contract tx storage observableSlots).sharedState store + : EvmYul.Yul.State).insert discrName discrValue).insert + matchedName (EvmYul.UInt256.ofNat 0))[matchedName]! = + EvmYul.UInt256.ofNat 0 := by + simp [EvmYul.Yul.State.insert, GetElem?.getElem!, decidableGetElem?, + GetElem.getElem, EvmYul.Yul.State.store, EvmYul.Yul.State.lookup!] + +/-- `discr := selector` lookup on the post-prefix state with arbitrary store. -/ +theorem nativeSwitchPrefixStoreState_discr_eq + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (discrName matchedName : EvmYul.Identifier) + (selector : Nat) (hne : discrName ≠ matchedName) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) : + (((.Ok (initialState contract tx storage observableSlots).sharedState store + : EvmYul.Yul.State).insert discrName + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + matchedName (EvmYul.UInt256.ofNat 0))[discrName]! = + EvmYul.UInt256.ofNat selector := by + rw [hSelector] + simp [EvmYul.Yul.State.insert, GetElem?.getElem!, decidableGetElem?, + GetElem.getElem, EvmYul.Yul.State.store, EvmYul.Yul.State.lookup!] + rw [Finmap.lookup_insert_of_ne] + · rw [Finmap.lookup_insert]; simp + · exact hne + +/-- Store-parametric prefix-then-tail-ok glue for `lowerNativeSwitchBlock`. + This is the success dual of + `exec_lowerNativeSwitchBlock_storePrefix_tail_error_fuel`: it lifts switch + tail proofs to states already carrying additional bindings while preserving + the final state returned by the tail. -/ +theorem exec_lowerNativeSwitchBlock_storePrefix_tail_ok_fuel + (fuel switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (final : EvmYul.Yul.State) + (hTail : + EvmYul.Yul.exec (fuel + 10) + (.Block (nativeSwitchTailStmts switchId cases defaultBody)) + (some contract) + (nativeSwitchStorePrefixStateForId contract tx storage observableSlots + switchId store) = .ok final) : + EvmYul.Yul.exec (fuel + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (nativeSwitchStoreInitialState contract tx storage observableSlots store) = + .ok final := by + let discrName := Backends.nativeSwitchDiscrTempName switchId + let matchedName := Backends.nativeSwitchMatchedTempName switchId + let initState := + nativeSwitchStoreInitialState contract tx storage observableSlots store + let prefixState := + nativeSwitchStorePrefixStateForId contract tx storage observableSlots + switchId store + rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] + apply exec_block_append_ok (fuel + 10) 0 + (nativeSwitchPrefixStmts discrName matchedName) + (nativeSwitchTailStmts switchId cases defaultBody) + (some contract) initState prefixState final + · simpa [nativeSwitchPrefixStmts, prefixState, initState, Nat.add_assoc, + Nat.add_comm, Nat.add_left_comm, nativeSwitchStorePrefixStateForId, + nativeSwitchStoreInitialState, discrName, matchedName] using + exec_nativeSwitchPrefix_selector_initialState_store_ok_fuel + fuel contract tx storage observableSlots store discrName matchedName + · simpa [prefixState, initState] using hTail + +/-- Store-parametric guarded selector-hit execution for the lowered switch + block. This is the success dual of + `exec_lowerNativeSwitchBlock_selector_find_hit_error_store_fuel`, retaining + the matched-flag preservation premise needed to skip the generated default + after a successful selected body. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_preserved_store_fuel + (fuel selector switchId tag : Nat) (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) (final : EvmYul.Yul.State) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx storage observableSlots switchId store) = .ok final) + (hPreservesMatched : ∀ pre suffix, + cases = pre ++ (tag, body) :: suffix → + NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) (EvmYul.UInt256.ofNat 1) + body (some contract)) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) (some contract) + (nativeSwitchStoreInitialState contract tx storage observableSlots store) = + .ok final := by + let discrName := Backends.nativeSwitchDiscrTempName switchId + let matchedName := Backends.nativeSwitchMatchedTempName switchId + have hne := nativeSwitchDiscrTempName_ne_matchedTempName switchId + have hCases := + exec_nativeSwitchCaseIfs_find_hit_with_default_preserved_fuel + (fuel + 1) selector cases defaultBody tag body (some contract) _ + final discrName matchedName hFind + (nativeSwitchPrefixStoreState_matched_eq contract tx storage + observableSlots store discrName matchedName _) + (nativeSwitchPrefixStoreState_discr_eq contract tx storage + observableSlots store discrName matchedName selector hne hSelector) + hSelectorRange hTagsRange + (by + simp [EvmYul.Yul.State.insert, GetElem?.getElem!, + decidableGetElem?, GetElem.getElem, EvmYul.Yul.State.store, + EvmYul.Yul.State.lookup!]) + hBody + (by intro pre suffix hCases; simpa [matchedName] using + hPreservesMatched pre suffix hCases) + exact exec_lowerNativeSwitchBlock_storePrefix_tail_ok_fuel + (fuel + cases.length) switchId cases defaultBody contract tx storage + observableSlots store final (by + simpa [nativeSwitchTailStmts, discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, + nativeSwitchStoreMarkedPrefixStateForId] using hCases) + +/-- Store-parametric selector-hit success when the selected body execution and + final matched-flag fact are supplied directly. This is useful for generated + case-body wrappers that prove the matched flag after peeling their own + prefix rather than exposing whole-body preservation. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_finalMatched_store_fuel + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (final : EvmYul.Yul.State) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx + storage observableSlots switchId store) = .ok final) + (hFinalMatched : + ∀ matchedName : EvmYul.Identifier, + matchedName = Backends.nativeSwitchMatchedTempName switchId → + final[matchedName]! = EvmYul.UInt256.ofNat 1) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (nativeSwitchStoreInitialState contract tx storage observableSlots store) = + .ok final := by + let discrName := Backends.nativeSwitchDiscrTempName switchId + let matchedName := Backends.nativeSwitchMatchedTempName switchId + have hne := nativeSwitchDiscrTempName_ne_matchedTempName switchId + have hCasesOnly : + EvmYul.Yul.exec (fuel + 1 + cases.length + 9) + (.Block (nativeSwitchCaseIfs discrName matchedName cases)) + (some contract) + (nativeSwitchStorePrefixStateForId contract tx storage + observableSlots switchId store) = .ok final := by + exact exec_nativeSwitchCaseIfs_find_hit_fuel + (fuel + 1) selector cases tag body (some contract) + (nativeSwitchStorePrefixStateForId contract tx storage observableSlots + switchId store) final discrName matchedName hFind + (nativeSwitchPrefixStoreState_matched_eq contract tx storage + observableSlots store discrName matchedName _) + (nativeSwitchPrefixStoreState_discr_eq contract tx storage + observableSlots store discrName matchedName selector hne hSelector) + hSelectorRange hTagsRange + (by + intro pre suffix hCases + simpa [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, discrName, matchedName, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + hBody pre suffix hCases) + (by simpa [matchedName] using hFinalMatched) + have hCasesDefault : + EvmYul.Yul.exec (fuel + 1 + cases.length + 9) + (.Block + (nativeSwitchCaseIfs discrName matchedName cases ++ + nativeSwitchDefaultIf matchedName defaultBody)) + (some contract) + (nativeSwitchStorePrefixStateForId contract tx storage + observableSlots switchId store) = .ok final := by + exact exec_nativeSwitchCaseIfs_with_default_matched_fuel + (fuel + 1) cases defaultBody (some contract) + (nativeSwitchStorePrefixStateForId contract tx storage + observableSlots switchId store) final discrName matchedName + hCasesOnly + (hFinalMatched matchedName rfl) + exact exec_lowerNativeSwitchBlock_storePrefix_tail_ok_fuel + (fuel + cases.length) switchId cases defaultBody contract tx storage + observableSlots store final (by + simpa [nativeSwitchTailStmts, discrName, matchedName, Nat.add_assoc, + Nat.add_comm, Nat.add_left_comm, nativeSwitchStorePrefixStateForId, + nativeSwitchStoreInitialState] using hCasesDefault) + +/-- Store-parametric selector-hit success derived from generated native switch + freshness. This removes the explicit matched-flag preservation premise for + selected bodies when the generated freshness predicate proves the body does + not write the matched temp. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_fresh_store_fuel + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (final : EvmYul.Yul.State) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx + storage observableSlots switchId store) = .ok final) + (hStmtPreserves : + ∀ stmt, stmt ∈ body → + Backends.nativeSwitchMatchedTempName switchId ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (nativeSwitchStoreInitialState contract tx storage observableSlots store) = + .ok final := by + apply exec_lowerNativeSwitchBlock_selector_find_hit_preserved_store_fuel + fuel selector switchId tag cases defaultBody body contract tx storage + observableSlots store final hSelector hFind hSelectorRange hTagsRange hBody + intro pre suffix _hCases + exact NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched + switchId selector tag body defaultBody cases (EvmYul.UInt256.ofNat 1) + (some contract) hFresh hFind hStmtPreserves + +/-- Store-parametric guarded selector-miss execution for the lowered switch + block whose default is `revert(0, 0)`. Lifts the empty-store version to + states already carrying additional bindings (e.g. `__has_selector := 1`). -/ +theorem exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_fuel + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + [nativeRevertZeroZeroStmt]) + (some contract) + (.Ok (initialState contract tx storage observableSlots).sharedState store) = + .error EvmYul.Yul.Exception.Revert := by + let discrName := Backends.nativeSwitchDiscrTempName switchId + let matchedName := Backends.nativeSwitchMatchedTempName switchId + have hne := nativeSwitchDiscrTempName_ne_matchedTempName switchId + have hCases := + exec_nativeSwitchCaseIfs_find_none_with_revert_default_fuel + (fuel + 1) selector cases (some contract) _ discrName matchedName hFind + (nativeSwitchPrefixStoreState_matched_eq contract tx storage observableSlots + store discrName matchedName _) + (nativeSwitchPrefixStoreState_discr_eq contract tx storage observableSlots + store discrName matchedName selector hne hSelector) + hSelectorRange hTagsRange + exact exec_lowerNativeSwitchBlock_storePrefix_tail_error_fuel + (fuel + cases.length) switchId cases [nativeRevertZeroZeroStmt] + contract tx storage observableSlots store EvmYul.Yul.Exception.Revert + (by simpa [nativeSwitchTailStmts, discrName, matchedName, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hCases) + +/-- Store-parametric guarded selector-hit execution for the lowered switch + block. Hit-case dual of `_find_none_with_revert_default_store_fuel`. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_error_store_fuel + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) + (err : EvmYul.Yul.Exception) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) + ((((.Ok (initialState contract tx storage observableSlots).sharedState + store : EvmYul.Yul.State).insert + (Backends.nativeSwitchDiscrTempName switchId) + (EvmYul.UInt256.ofNat + (tx.functionSelector % Compiler.Constants.selectorModulus))).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 0)).insert + (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1)) = .error err) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (.Ok (initialState contract tx storage observableSlots).sharedState store) = + .error err := by + let discrName := Backends.nativeSwitchDiscrTempName switchId + let matchedName := Backends.nativeSwitchMatchedTempName switchId + have hne := nativeSwitchDiscrTempName_ne_matchedTempName switchId + have hCases := + exec_nativeSwitchCaseIfs_find_hit_with_default_error_fuel + (fuel + 1) selector cases defaultBody tag body (some contract) _ + discrName matchedName err hFind + (nativeSwitchPrefixStoreState_matched_eq contract tx storage + observableSlots store discrName matchedName _) + (nativeSwitchPrefixStoreState_discr_eq contract tx storage + observableSlots store discrName matchedName selector hne hSelector) + hSelectorRange hTagsRange hBody + exact exec_lowerNativeSwitchBlock_storePrefix_tail_error_fuel + (fuel + cases.length) switchId cases defaultBody contract tx storage + observableSlots store err + (by simpa [nativeSwitchTailStmts, discrName, matchedName, + Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hCases) + +/-- Bridge-shape selector-miss endpoint on the post-`__has_selector := 1` + state, yielding `.error Revert`. -/ +theorem exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 13) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) = + .error EvmYul.Yul.Exception.Revert := by + have hEndpoint := + exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_fuel + fuel selector switchId cases contract tx storage observableSlots + ((∅ : EvmYul.Yul.VarStore).insert "__has_selector" (EvmYul.UInt256.ofNat 1)) + hSelector hFind hSelectorRange hTagsRange + have hStateEq : + (nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1) = + .Ok (initialState contract tx storage observableSlots).sharedState + ((∅ : EvmYul.Yul.VarStore).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + simp [nativeSwitchInitialOkState, EvmYul.Yul.State.insert] + rw [hStateEq] + have hFuelEq : fuel + cases.length + 13 = (fuel + cases.length + 12).succ := by + omega + rw [hFuelEq] + exact exec_block_cons_error (fuel + cases.length + 12) _ [] _ _ + EvmYul.Yul.Exception.Revert hEndpoint + +/-- Bridge-shape selector-hit endpoint on the post-`__has_selector := 1` + state, yielding `.error err`. Hit-case dual of + `exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error`. -/ +theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx + storage observableSlots switchId nativeSwitchHasSelectorStore) = + .error err) : + EvmYul.Yul.exec (fuel + cases.length + 13) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) = + .error err := by + have hEndpoint := exec_lowerNativeSwitchBlock_selector_find_hit_error_store_fuel + fuel selector switchId tag cases defaultBody body contract tx storage + observableSlots nativeSwitchHasSelectorStore err hSelector hFind + hSelectorRange hTagsRange (by + intro pre suffix hCases + simpa [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, + nativeSwitchHasSelectorStore] using hBody pre suffix hCases) + have hFuelEq : fuel + cases.length + 13 = (fuel + cases.length + 12).succ := by omega + rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] + exact exec_block_cons_error (fuel + cases.length + 12) _ [] _ _ err hEndpoint + +/-- Bridge-shape selector-hit endpoint on the post-`__has_selector := 1` + state, yielding the selected body's successful final state. This is the + success dual of + `exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error` + and derives the default-skip preservation premise from generated native + switch freshness. -/ +theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_fresh + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) + (final : EvmYul.Yul.State) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hFresh : + Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId nativeSwitchHasSelectorStore) = .ok final) + (hStmtPreserves : + ∀ stmt, stmt ∈ body → + Backends.nativeSwitchMatchedTempName switchId ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) : + EvmYul.Yul.exec (fuel + cases.length + 13) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) = + .ok final := by + have hEndpoint := + exec_lowerNativeSwitchBlock_selector_find_hit_fresh_store_fuel + fuel selector switchId tag cases defaultBody body contract tx storage + observableSlots nativeSwitchHasSelectorStore final hSelector hFind + hSelectorRange hTagsRange hFresh hBody hStmtPreserves + have hFuelEq : fuel + cases.length + 13 = (fuel + cases.length + 12).succ := by + omega + rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] + exact exec_block_cons_ok (fuel + cases.length + 12) _ [] _ _ final final + hEndpoint (by simp [EvmYul.Yul.exec]) + +theorem exec_lowerNativeSwitchBlock_selector_find_none_without_default_fuel + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases []) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .ok (nativeSwitchPrefixFinalState contract tx storage observableSlots + (Backends.nativeSwitchDiscrTempName switchId) + (Backends.nativeSwitchMatchedTempName switchId)) := by + rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] + apply exec_nativeSwitchPrefix_then_tail_fuel + exact exec_nativeSwitchTail_find_none_without_default_fuel fuel selector + switchId cases contract tx storage observableSlots hSelector hFind + hSelectorRange hTagsRange + +@[simp] theorem initialState_unbridgedEnvironmentDefaults + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) : + (initialState contract tx storage observableSlots).sharedState.executionEnv.header.baseFeePerGas = + 0 ∧ + (initialState contract tx storage observableSlots).sharedState.executionEnv.header.blobGasUsed = + (0 : UInt64) ∧ + (initialState contract tx storage observableSlots).sharedState.executionEnv.header.excessBlobGas = + (0 : UInt64) ∧ + (initialState contract tx storage observableSlots).sharedState.executionEnv.blobVersionedHashes = + [] ∧ + EvmYul.State.chainId + (initialState contract tx storage observableSlots).sharedState.toState = + EvmYul.UInt256.ofNat EvmYul.chainId := by + simp [initialState, EvmYul.Yul.State.sharedState, YulState.initial, toSharedState, + mkBlockHeader, EvmYul.State.chainId] + +/-- Project the account storage for the current contract back to Verity's + `IRStorageSlot → IRStorageWord` storage view. -/ +def projectStorageFromState (tx : YulTransaction) (state : EvmYul.Yul.State) : + IRStorageSlot → IRStorageWord := + extractStorage state.sharedState (natToAddress tx.thisAddress) + +/-- Projecting final native storage reads the current contract account storage + entry for the requested slot. -/ +@[simp] theorem projectStorageFromState_accountStorageSlot + (tx : YulTransaction) + (state : EvmYul.Yul.State) + (slot : Nat) + (account : EvmYul.Account .Yul) + (value : EvmYul.UInt256) + (hAccount : + state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = + some account) + (hSlot : account.storage.find? (natToUInt256 slot) = some value) : + projectStorageFromState tx state (IRStorageSlot.ofNat slot) = value := by + simp [projectStorageFromState, extractStorage, hAccount, hSlot] + +/-- Projecting final native storage defaults to zero when the current contract + account has no native storage entry for the requested slot. -/ +@[simp] theorem projectStorageFromState_missingAccountStorageSlot + (tx : YulTransaction) + (state : EvmYul.Yul.State) + (slot : Nat) + (account : EvmYul.Account .Yul) + (hAccount : + state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = + some account) + (hSlot : account.storage.find? (natToUInt256 slot) = none) : + projectStorageFromState tx state (IRStorageSlot.ofNat slot) = 0 := by + simp [projectStorageFromState, extractStorage, hAccount, hSlot] + +/-- Projecting final native storage defaults to zero when the current contract + account is absent from the native account map. -/ +@[simp] theorem projectStorageFromState_missingAccount + (tx : YulTransaction) + (state : EvmYul.Yul.State) + (slot : Nat) + (hAccount : + state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = + none) : + projectStorageFromState tx state (IRStorageSlot.ofNat slot) = 0 := by + simp [projectStorageFromState, extractStorage, hAccount] + +/-- Native initial-state storage materialization agrees with Verity storage on + every explicit observable slot. Slots and values are interpreted in the + EVM word domain, so the result is modulo `UInt256.size`. -/ +theorem initialState_observableStorageSlot + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (slot : Nat) + (hSlot : slot ∈ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + projectStorageFromState tx + (initialState contract tx storage observableSlots) (IRStorageSlot.ofNat slot) = + storage (IRStorageSlot.ofNat slot) := by + simp only [projectStorageFromState, extractStorage, initialState, + EvmYul.Yul.State.sharedState, YulState.initial, toSharedState] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + have h := storageLookup_projectStorage storage observableSlots slot hSlot hRange + unfold storageLookup at h + exact h + +/-- Native initial-state storage materialization agrees with Verity storage on + every explicitly materialized slot. This is the range-free form used by the + generated native dispatcher path, whose materialization list is already in + bounded `IRStorageSlot` space. -/ +theorem initialState_materializedStorageSlot + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (slots : List Nat) + (slot : Nat) + (hSlot : slot ∈ slots) : + projectStorageFromState tx + (initialState contract tx storage slots) (IRStorageSlot.ofNat slot) = + storage (IRStorageSlot.ofNat slot) := by + simp only [projectStorageFromState, extractStorage, initialState, + EvmYul.Yul.State.sharedState, YulState.initial, toSharedState] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + have h := storageLookup_projectStorage_projected storage slots slot hSlot + unfold storageLookup at h + exact h + +/-- The generated selector-hit marked-prefix state only changes native local + variables. Projected contract storage still agrees with every materialized + Verity storage slot. -/ +theorem nativeSwitchStoreMarkedPrefixStateForId_materializedStorageSlot + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (slots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (slot : Nat) + (hSlot : slot ∈ slots) : + projectStorageFromState tx + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage slots + switchId store) + (IRStorageSlot.ofNat slot) = + storage (IRStorageSlot.ofNat slot) := by + simpa [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert, projectStorageFromState, + EvmYul.Yul.State.sharedState] using + (initialState_materializedStorageSlot contract tx storage slots slot hSlot) + +/-- Native `sload` from an initially materialized observable slot returns the + exact EVM word projected from Verity storage. The range hypothesis keeps + the slot key word-canonical, so the finite native storage map cannot alias + another observed slot. -/ +theorem initialState_sload_observableSlot_value + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (slot : Nat) + (hSlot : slot ∈ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + (EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 slot)).2 = + storage (IRStorageSlot.ofNat slot) := by + have hFindStorage : + (projectStorage storage observableSlots).find? (natToUInt256 slot) = + some (storage (IRStorageSlot.ofNat slot)) := by + simpa [projectStorage, IRStorageWord.toUInt256] using + foldl_insert_find storage observableSlots slot hSlot hRange + (Batteries.RBMap.empty : EvmYul.Storage) + simp only [EvmYul.State.sload, EvmYul.State.lookupAccount, + EvmYul.Yul.State.toState, initialState, toSharedState, YulState.initial] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + change (Batteries.RBMap.find? (projectStorage storage observableSlots) + (natToUInt256 slot)).getD ⟨0⟩ = storage (IRStorageSlot.ofNat slot) + rw [hFindStorage] + rfl + +/-- Native `sload` from an initially materialized slot returns the exact bounded + IR storage word. This is the range-free version used after IR storage keys + moved to `IRStorageSlot`: Nat aliases modulo 2^256 carry the same bounded + key and therefore the same projected value. -/ +theorem initialState_sload_materializedSlot_value + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (slots : List Nat) + (slot : Nat) + (hSlot : slot ∈ slots) : + (EvmYul.State.sload + (initialState contract tx storage slots).toState + (natToUInt256 slot)).2 = + storage (IRStorageSlot.ofNat slot) := by + have hFindStorage : + (projectStorage storage slots).find? (natToUInt256 slot) = + some (storage (IRStorageSlot.ofNat slot)) := by + simpa [projectStorage, IRStorageWord.toUInt256] using + foldl_insert_find_projected storage slots slot hSlot + (Batteries.RBMap.empty : EvmYul.Storage) + simp only [EvmYul.State.sload, EvmYul.State.lookupAccount, + EvmYul.Yul.State.toState, initialState, toSharedState, YulState.initial] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + change (Batteries.RBMap.find? (projectStorage storage slots) + (natToUInt256 slot)).getD ⟨0⟩ = storage (IRStorageSlot.ofNat slot) + rw [hFindStorage] + rfl + +/-- Projected storage is unchanged by the generated retrieve core + `sload(0); mstore(0, _); return(0, 32)`. The only `sload` state effect is + recording an accessed storage key, and `mstore`/`return` update only the + machine-state fields used for returndata. -/ +theorem projectStorageFromState_retrieveHit_initialState_materialized + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (slots : List Nat) + (store : EvmYul.Yul.VarStore) + (slot : Nat) + (hSlot : slot ∈ slots) : + let shared := (initialState contract tx storage slots).sharedState + let p := shared.sload (EvmYul.UInt256.ofNat 0) + let shared1 : EvmYul.SharedState .Yul := { shared with toState := p.1 } + let shared2 : EvmYul.SharedState .Yul := + { shared1 with + toMachineState := + shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) p.2 } + let shared3 : EvmYul.SharedState .Yul := + { shared2 with + toMachineState := + shared2.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } + projectStorageFromState tx (EvmYul.Yul.State.Ok shared3 store) + (IRStorageSlot.ofNat slot) = + storage (IRStorageSlot.ofNat slot) := by + intro shared p shared1 shared2 shared3 + have hAccountMap : + shared3.accountMap = + (initialState contract tx storage slots).sharedState.accountMap := by + simp [shared3, shared2, shared1, p, shared, EvmYul.State.sload, + EvmYul.State.addAccessedStorageKey, EvmYul.Substate.addAccessedStorageKey] + simp only [projectStorageFromState, extractStorage, + EvmYul.Yul.State.sharedState, hAccountMap, initialState, YulState.initial, + toSharedState] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + have h := storageLookup_projectStorage_projected storage slots slot hSlot + unfold storageLookup at h + exact h + +/-- Native `sload` from an initially omitted materialized slot returns the EVM + zero word. The range hypotheses rule out modular aliasing between the omitted + slot and any materialized storage key. -/ +theorem initialState_sload_omittedSlot_value + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (slot : Nat) + (hNotSlot : slot ∉ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) + (hSlotRange : slot < EvmYul.UInt256.size) : + (EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 slot)).2 = + natToUInt256 0 := by + have hFindStorage : + (projectStorage storage observableSlots).find? (natToUInt256 slot) = none := by + simpa [projectStorage] using + foldl_insert_find_not_mem storage observableSlots slot hNotSlot hRange + hSlotRange (Batteries.RBMap.empty : EvmYul.Storage) + simp only [EvmYul.State.sload, EvmYul.State.lookupAccount, + EvmYul.Yul.State.toState, initialState, toSharedState, YulState.initial] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + change (Batteries.RBMap.find? (projectStorage storage observableSlots) + (natToUInt256 slot)).getD ⟨0⟩ = natToUInt256 0 + rw [hFindStorage] + rfl + +/-- Native primitive execution of `sload(slot)` on an initially materialized, + word-canonical observable slot returns exactly the projected storage word. -/ +theorem primCall_sload_initialState_observableSlot_ok + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (slot : Nat) + (hSlot : slot ∈ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + EvmYul.Yul.primCall (fuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.SLOAD [natToUInt256 slot] = + match EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 slot) with + | (state', _) => + .ok ((initialState contract tx storage observableSlots).setSharedState + { (initialState contract tx storage observableSlots).toSharedState with + toState := state' }, + [storage (IRStorageSlot.ofNat slot)]) := by + rw [primCall_sload_ok] + generalize hload : + EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 slot) = loaded + cases loaded with + | mk state' value => + have hvalue := + initialState_sload_observableSlot_value contract tx storage + observableSlots slot hSlot hRange + rw [hload] at hvalue + simp only at hvalue + simp [hvalue] + +/-- Native primitive execution of `sload(slot)` on an initially omitted, + word-canonical materialization slot returns the EVM zero word. -/ +theorem primCall_sload_initialState_omittedSlot_ok + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (slot : Nat) + (hNotSlot : slot ∉ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) + (hSlotRange : slot < EvmYul.UInt256.size) : + EvmYul.Yul.primCall (fuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.SLOAD [natToUInt256 slot] = + match EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 slot) with + | (state', _) => + .ok ((initialState contract tx storage observableSlots).setSharedState + { (initialState contract tx storage observableSlots).toSharedState with + toState := state' }, + [natToUInt256 0]) := by + rw [primCall_sload_ok] + generalize hload : + EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 slot) = loaded + cases loaded with + | mk state' value => + have hvalue := + initialState_sload_omittedSlot_value contract tx storage + observableSlots slot hNotSlot hRange hSlotRange + rw [hload] at hvalue + simp only at hvalue + simp [hvalue] + +/-- Native primitive execution of `sload(slot)` is independent of the current + Yul local-variable store when reading an initially materialized, + word-canonical observable slot. This is the selected-body shape left after + the lowered dispatcher inserts switch temporaries. -/ +theorem primCall_sload_initialState_observableSlot_ok_withStore + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (slot : Nat) + (hSlot : slot ∈ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + EvmYul.Yul.primCall (fuel + 1) + (.Ok (initialState contract tx storage observableSlots).sharedState store) + EvmYul.Operation.SLOAD [natToUInt256 slot] = + match EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 slot) with + | (state', _) => + .ok (((.Ok (initialState contract tx storage observableSlots).sharedState + store : EvmYul.Yul.State).setSharedState + { (.Ok (initialState contract tx storage observableSlots).sharedState + store : EvmYul.Yul.State).toSharedState with + toState := state' }), + [storage (IRStorageSlot.ofNat slot)]) := by + rw [primCall_sload_ok] + generalize hload : + EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 slot) = loaded + cases loaded with + | mk state' value => + have hloadShared : + (initialState contract tx storage observableSlots).sharedState.sload + (natToUInt256 slot) = (state', value) := by + simpa [EvmYul.Yul.State.toState] using hload + have hvalue := + initialState_sload_observableSlot_value contract tx storage + observableSlots slot hSlot hRange + rw [hload] at hvalue + simp only at hvalue + simp [hloadShared, hvalue, EvmYul.Yul.State.toState] + +/-- Native primitive execution of `sload(slot)` is independent of the current + Yul local-variable store when reading an omitted word-canonical slot. -/ +theorem primCall_sload_initialState_omittedSlot_ok_withStore + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (slot : Nat) + (hNotSlot : slot ∉ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) + (hSlotRange : slot < EvmYul.UInt256.size) : + EvmYul.Yul.primCall (fuel + 1) + (.Ok (initialState contract tx storage observableSlots).sharedState store) + EvmYul.Operation.SLOAD [natToUInt256 slot] = + match EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 slot) with + | (state', _) => + .ok (((.Ok (initialState contract tx storage observableSlots).sharedState + store : EvmYul.Yul.State).setSharedState + { (.Ok (initialState contract tx storage observableSlots).sharedState + store : EvmYul.Yul.State).toSharedState with + toState := state' }), + [natToUInt256 0]) := by + rw [primCall_sload_ok] + generalize hload : + EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 slot) = loaded + cases loaded with + | mk state' value => + have hloadShared : + (initialState contract tx storage observableSlots).sharedState.sload + (natToUInt256 slot) = (state', value) := by + simpa [EvmYul.Yul.State.toState] using hload + have hvalue := + initialState_sload_omittedSlot_value contract tx storage + observableSlots slot hNotSlot hRange hSlotRange + rw [hload] at hvalue + simp only at hvalue + simp [hloadShared, hvalue, EvmYul.Yul.State.toState] + +/-- Native primitive execution of `sstore(slot, value)` on an initial runtime + state succeeds with the exact EVMYulLean `State.sstore` successor. The + range hypothesis records the word-canonical slot condition needed by the + dispatcher proof when this lemma is connected to projected storage. -/ +theorem primCall_sstore_initialState_wordSlot_ok + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (slot value : Nat) + (_hSlotRange : slot < EvmYul.UInt256.size) : + EvmYul.Yul.primCall (fuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = + .ok (((initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (natToUInt256 slot) (natToUInt256 value))), []) := by + rw [primCall_sstore_ok] + simp [initialState, EvmYul.Yul.State.executionEnv] + +/-- Native primitive execution of `sstore(slot, value)` from an initial runtime + shared state is independent of the current Yul local-variable store. This + packages the word-slot storage write in the shape produced after dispatcher + switch temporaries have been inserted. -/ +theorem primCall_sstore_initialState_wordSlot_ok_withStore + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (slot value : Nat) + (_hSlotRange : slot < EvmYul.UInt256.size) : + EvmYul.Yul.primCall (fuel + 1) + (.Ok (initialState contract tx storage observableSlots).sharedState store) + EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = + .ok (((.Ok (initialState contract tx storage observableSlots).sharedState store : + EvmYul.Yul.State).setState + ((.Ok (initialState contract tx storage observableSlots).sharedState store : + EvmYul.Yul.State).toState.sstore + (natToUInt256 slot) (natToUInt256 value))), []) := by + rw [primCall_sstore_ok] + simp [initialState, EvmYul.Yul.State.sharedState, + EvmYul.Yul.State.executionEnv, YulState.initial, toSharedState] + +/-- Native primitive execution of the generated `store(uint256)` core: + `calldataload(4)` decodes the first ABI argument and the following + `sstore(0, value)` writes that word to slot zero. This is the real native + primitive sequence under the emitted SimpleStorage setter body, before the + terminating `stop`. -/ +theorem primCall_calldataload4_then_sstore0_initialState_arg0_ok + (loadFuel storeFuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) : + (do + let (state', values) ← + EvmYul.Yul.primCall (loadFuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] + match values with + | [value] => + EvmYul.Yul.primCall (storeFuel + 1) state' + EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .ok (((initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg))), []) := by + rw [primCall_calldataload4_initialState_arg0_ok loadFuel contract tx storage + observableSlots arg rest hArgs] + change EvmYul.Yul.primCall (storeFuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, natToUInt256 arg] = + .ok (((initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg))), []) + exact primCall_sstore_initialState_wordSlot_ok storeFuel contract tx storage + observableSlots 0 arg (by norm_num [EvmYul.UInt256.size]) + +/-- Native primitive execution of the `return(0, 32)` half of the generated + scalar-return sequence after `mstore(0, value)`. EVMYulLean models `RETURN` + as a Yul halt carrying the post-`evmReturn` state; the halt literal is the + default nonzero marker produced by `binaryMachineStateOp`, while the actual + returned bytes live in the state's `H_return` buffer. -/ +theorem primCall_return32_after_mstore0_ok + (fuel : Nat) + (state : EvmYul.Yul.State) + (value : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) + (state.setMachineState + (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value)) + EvmYul.Operation.RETURN + [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] = + .error (EvmYul.Yul.Exception.YulHalt + ((state.setMachineState + (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value)).setMachineState + ((state.setMachineState + (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value)).toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32))) + ⟨1⟩) := by + rw [primCall_return_ok] + simp [EvmYul.Yul.binaryMachineStateOp] + +/-- Native primitive execution of the generated scalar-return instruction pair + through EVMYulLean's actual `MSTORE` and `RETURN` primitive relation. This + exposes the exact halt state that remains to be connected to Verity's + single-word `returnValue` projection. -/ +theorem primCall_mstore0_then_return32_ok + (mstoreFuel returnFuel : Nat) + (state : EvmYul.Yul.State) + (value : EvmYul.UInt256) : + (do + let (state', values) ← + EvmYul.Yul.primCall (mstoreFuel + 1) state + EvmYul.Operation.MSTORE + [EvmYul.UInt256.ofNat 0, value] + match values with + | [] => + EvmYul.Yul.primCall (returnFuel + 1) state' + EvmYul.Operation.RETURN + [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .error (EvmYul.Yul.Exception.YulHalt + ((state.setMachineState + (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value)).setMachineState + ((state.setMachineState + (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value)).toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32))) + ⟨1⟩) := by + rw [primCall_mstore_ok] + exact primCall_return32_after_mstore0_ok returnFuel state value + +/-- The native return buffer produced by `mstore(0, value); return(0, 32)` is + exactly one EVM word wide. -/ +theorem mstore0_then_return32_hReturn_size + (sharedState : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (value : EvmYul.UInt256) : + let state : EvmYul.Yul.State := .Ok sharedState store + let stored := + state.setMachineState + (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value) + let returned := + stored.setMachineState + (stored.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32)) + returned.sharedState.H_return.size = 32 := by + dsimp + have hZero : (EvmYul.UInt256.ofNat 0).toNat = 0 := by + rfl + have hLen : (EvmYul.UInt256.ofNat 32).toNat = 32 := by + rfl + simp [EvmYul.MachineState.evmReturn, readWithPadding_32_size, + EvmYul.MachineState.mstore, + EvmYul.MachineState.writeWord, EvmYul.writeBytes, + EvmYul.UInt256.toByteArray, EvmYul.Yul.State.setMachineState, + EvmYul.Yul.State.sharedState, EvmYul.Yul.State.toMachineState, hZero, hLen] + +/-- If the generated scalar-return sequence starts from empty memory and the + value word is represented by exactly 32 bytes, then the native `RETURN` + halt buffer is byte-for-byte the word written by `MSTORE`. -/ +theorem mstore0_then_return32_emptyMemory_hReturn_eq + (sharedState : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (value : EvmYul.UInt256) + (hMemory : sharedState.memory = ByteArray.empty) + (hValueSize : value.toByteArray.size = 32) : + let state : EvmYul.Yul.State := .Ok sharedState store + let stored := + state.setMachineState + (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value) + let returned := + stored.setMachineState + (stored.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32)) + returned.sharedState.H_return = value.toByteArray := by + dsimp + simp only [EvmYul.Yul.State.toMachineState, EvmYul.Yul.State.setMachineState, + EvmYul.Yul.State.sharedState] + simp only [EvmYul.MachineState.mstore, EvmYul.MachineState.writeWord, + EvmYul.writeBytes, EvmYul.MachineState.evmReturn] + simp only [hMemory] + exact byteArray_write_empty_zero_32_readWithPadding_eq_of_size + value.toByteArray hValueSize + +/-- The generated scalar-return sequence started from empty memory returns + exactly the 32-byte representation of the word written at offset zero. -/ +theorem mstore0_then_return32_emptyMemory_hReturn_eq_toByteArray + (sharedState : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (value : EvmYul.UInt256) + (hMemory : sharedState.memory = ByteArray.empty) : + let state : EvmYul.Yul.State := .Ok sharedState store + let stored := + state.setMachineState + (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value) + let returned := + stored.setMachineState + (stored.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32)) + returned.sharedState.H_return = value.toByteArray := + mstore0_then_return32_emptyMemory_hReturn_eq sharedState store value hMemory + (uint256_toByteArray_size value) + +/-- The concrete native primitive execution theorem for the generated scalar + return sequence carries a one-word return buffer when started from an + executable `Ok` Yul state. -/ +theorem primCall_mstore0_then_return32_ok_hReturn_size + (mstoreFuel returnFuel : Nat) + (sharedState : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (value : EvmYul.UInt256) : + ∃ haltState haltValue, + (do + let (state', values) ← + EvmYul.Yul.primCall (mstoreFuel + 1) (.Ok sharedState store) + EvmYul.Operation.MSTORE + [EvmYul.UInt256.ofNat 0, value] + match values with + | [] => + EvmYul.Yul.primCall (returnFuel + 1) state' + EvmYul.Operation.RETURN + [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + haltState.sharedState.H_return.size = 32 := by + refine ⟨ + ((EvmYul.Yul.State.Ok sharedState store).setMachineState + ((EvmYul.Yul.State.Ok sharedState store).toMachineState.mstore + (EvmYul.UInt256.ofNat 0) value)).setMachineState + (((EvmYul.Yul.State.Ok sharedState store).setMachineState + ((EvmYul.Yul.State.Ok sharedState store).toMachineState.mstore + (EvmYul.UInt256.ofNat 0) value)).toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32)), + ⟨1⟩, ?_⟩ + constructor + · exact primCall_mstore0_then_return32_ok mstoreFuel returnFuel + (.Ok sharedState store) value + · exact mstore0_then_return32_hReturn_size sharedState store value + +/-- Native initial-state storage materialization defaults omitted observable + pre-state slots to zero. The in-range hypotheses rule out modular aliasing + through the EVM word key used by the finite native storage map. -/ +theorem initialState_omittedStorageSlot + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (slot : Nat) + (hNotSlot : slot ∉ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) + (hSlotRange : slot < EvmYul.UInt256.size) : + projectStorageFromState tx + (initialState contract tx storage observableSlots) (IRStorageSlot.ofNat slot) = 0 := by + simp only [projectStorageFromState, extractStorage, initialState, + EvmYul.Yul.State.sharedState, YulState.initial, toSharedState] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] + simp only + have h := foldl_insert_find_not_mem storage observableSlots slot hNotSlot + hRange hSlotRange (Batteries.RBMap.empty : EvmYul.Storage) + have hNone : + (projectStorage storage observableSlots).find? (natToUInt256 slot) = none := by + simpa [projectStorage] using h + simp [IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hNone] + +/-- Decode one 32-byte big-endian word from an EVMYulLean byte array. -/ +def byteArrayWord (bytes : ByteArray) (offset : Nat) : Nat := + (List.range 32).foldl + (fun acc i => (acc * 256 + ((bytes.get? (offset + i)).getD 0).toNat) % + Compiler.Constants.evmModulus) + 0 + +private def listByteArrayWordNoMod (bytes : List UInt8) (n : Nat) : Nat := + (List.range n).foldl + (fun acc i => acc * 256 + ((bytes[i]?).getD 0).toNat) 0 + +private def listByteArrayWordMod (bytes : List UInt8) (n : Nat) : Nat := + (List.range n).foldl + (fun acc i => (acc * 256 + ((bytes[i]?).getD 0).toNat) % + Compiler.Constants.evmModulus) 0 + +private theorem fromBytes'_reverse_append_single (xs : List UInt8) (b : UInt8) : + EvmYul.fromBytes' ((xs ++ [b]).reverse) = + EvmYul.fromBytes' xs.reverse * 256 + b.toNat := by + simp [EvmYul.fromBytes'] + omega + +private theorem listByteArrayWordNoMod_eq_fromBytes'_take_reverse + (bytes : List UInt8) (n : Nat) + (hn : n ≤ bytes.length) : + listByteArrayWordNoMod bytes n = + EvmYul.fromBytes' (bytes.take n).reverse := by + induction n with + | zero => + simp [listByteArrayWordNoMod, EvmYul.fromBytes'] + | succ n ih => + have hn' : n ≤ bytes.length := by omega + have hlt : n < bytes.length := by omega + unfold listByteArrayWordNoMod at ih ⊢ + rw [List.range_succ, List.foldl_append] + simp only [List.foldl_cons, List.foldl_nil] + rw [ih hn'] + rw [List.take_succ] + rw [List.getElem?_eq_getElem hlt] + simp only [Option.getD_some, Option.toList_some] + rw [fromBytes'_reverse_append_single] + +private theorem listByteArrayWordNoMod_lt + (bytes : List UInt8) (n : Nat) + (hn : n ≤ bytes.length) : + listByteArrayWordNoMod bytes n < 2 ^ (8 * n) := by + rw [listByteArrayWordNoMod_eq_fromBytes'_take_reverse bytes n hn] + have h := fromBytes'_lt (bytes.take n).reverse + have hlen : (bytes.take n).reverse.length = n := by + simp [List.length_take, hn] + simpa [hlen] using h + +private theorem listByteArrayWordMod_eq_noMod + (bytes : List UInt8) (n : Nat) + (hnLen : n ≤ bytes.length) (hnWord : n ≤ 32) : + listByteArrayWordMod bytes n = listByteArrayWordNoMod bytes n := by + induction n with + | zero => + simp [listByteArrayWordMod, listByteArrayWordNoMod] + | succ n ih => + have hnLen' : n ≤ bytes.length := by omega + have hnWord' : n ≤ 32 := by omega + unfold listByteArrayWordMod listByteArrayWordNoMod at ih ⊢ + rw [List.range_succ, List.foldl_append, List.foldl_append] + simp only [List.foldl_cons, List.foldl_nil] + rw [ih hnLen' hnWord'] + have hNoMod : + (List.foldl (fun acc i => acc * 256 + (bytes[i]?.getD 0).toNat) 0 + (List.range n) * + 256 + + (bytes[n]?.getD 0).toNat) < Compiler.Constants.evmModulus := by + rw [show + List.foldl (fun acc i => acc * 256 + (bytes[i]?.getD 0).toNat) + 0 (List.range n) = + listByteArrayWordNoMod bytes n by rfl] + have hprev := listByteArrayWordNoMod_lt bytes n hnLen' + have hb : (bytes[n]?.getD 0).toNat < 256 := by + cases hopt : bytes[n]? + · simp + · simp + exact UInt8.toNat_lt _ + have hpow : 2 ^ (8 * n) * 256 = 2 ^ (8 * (n + 1)) := by + rw [Nat.mul_add, Nat.pow_add] + have hle : 2 ^ (8 * (n + 1)) ≤ Compiler.Constants.evmModulus := by + have : 8 * (n + 1) ≤ 256 := by omega + unfold Compiler.Constants.evmModulus + exact Nat.pow_le_pow_right (by norm_num) this + nlinarith + rw [Nat.mod_eq_of_lt hNoMod] + +private theorem byteArray_get?_data_toList (bytes : ByteArray) (i : Nat) : + bytes.get? i = bytes.data.toList[i]? := by + unfold ByteArray.get? + split + · rw [Array.getElem?_toList] + simp [ByteArray.get] + · rename_i h + have hlen : bytes.data.toList.length ≤ i := by + simp [ByteArray.size] at h + simpa using h + have hnone : bytes.data.toList[i]? = none := List.getElem?_eq_none hlen + exact hnone.symm + +theorem byteArrayWord_eq_fromBytes'_reverse_of_size + (bytes : ByteArray) + (hSize : bytes.size = 32) : + byteArrayWord bytes 0 = EvmYul.fromBytes' bytes.data.toList.reverse := by + have hLen : bytes.data.toList.length = 32 := by + simpa [ByteArray.size] using hSize + unfold byteArrayWord + rw [show + List.foldl + (fun acc i => (acc * 256 + ((bytes.get? (0 + i)).getD 0).toNat) % + Compiler.Constants.evmModulus) + 0 (List.range 32) = + listByteArrayWordMod bytes.data.toList 32 by + simp [listByteArrayWordMod, byteArray_get?_data_toList]] + rw [listByteArrayWordMod_eq_noMod bytes.data.toList 32 (by omega) (by omega)] + have hNoMod := + listByteArrayWordNoMod_eq_fromBytes'_take_reverse bytes.data.toList 32 + (by omega) + rw [hNoMod] + rw [show bytes.data.toList.take 32 = bytes.data.toList by + rw [← hLen, List.take_length]] + +private theorem fromBytes'_replicate_zero (n : Nat) : + EvmYul.fromBytes' (List.replicate n (0 : UInt8)) = 0 := by + induction n with + | zero => + simp [EvmYul.fromBytes'] + | succ n ih => + simp [List.replicate, EvmYul.fromBytes', ih] + +private theorem fromBytes'_append_replicate_zero (xs : List UInt8) (n : Nat) : + EvmYul.fromBytes' (xs ++ List.replicate n (0 : UInt8)) = + EvmYul.fromBytes' xs := by + rw [fromBytes'_append] + simp [fromBytes'_replicate_zero] + +theorem byteArrayWord_uint256_toByteArray + (value : EvmYul.UInt256) : + byteArrayWord value.toByteArray 0 = value.toNat := by + rw [byteArrayWord_eq_fromBytes'_reverse_of_size + value.toByteArray (uint256_toByteArray_size value)] + unfold EvmYul.UInt256.toByteArray BE + simp [ByteArray.data_append, ffi.ByteArray.zeroes, + list_toByteArray_data_toList] + simp [EvmYul.toBytesBigEndian] -/-- Selector-miss execution for the generated case chain when no default is - emitted. -/ -theorem exec_nativeSwitchCaseIfs_find_none_without_default_fuel - (fuel selector : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state : EvmYul.Yul.State) - (discrName matchedName : EvmYul.Identifier) - (hFind : - cases.find? (fun entry => entry.1 == selector) = none) - (hMatched : state[matchedName]! = EvmYul.UInt256.ofNat 0) - (hDiscrSelector : state[discrName]! = EvmYul.UInt256.ofNat selector) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block - (nativeSwitchCaseIfs discrName matchedName cases ++ - nativeSwitchDefaultIf matchedName [])) - codeOverride state = .ok state := by - have hCases : - EvmYul.Yul.exec (fuel + cases.length + 9) - (.Block (nativeSwitchCaseIfs discrName matchedName cases)) - codeOverride state = .ok state := - exec_nativeSwitchCaseIfs_find_none_fuel fuel selector cases codeOverride - state discrName matchedName hFind hMatched hDiscrSelector hSelectorRange - hTagsRange - have hDefault : - EvmYul.Yul.exec (fuel + 9) - (.Block (nativeSwitchDefaultIf matchedName [])) - codeOverride state = .ok state := by - simp [nativeSwitchDefaultIf, EvmYul.Yul.exec] - simpa [nativeSwitchCaseIfs, nativeSwitchDefaultIf, Nat.add_assoc, - Nat.add_comm, Nat.add_left_comm] using - (exec_block_append_ok fuel 9 - (nativeSwitchCaseIfs discrName matchedName cases) - (nativeSwitchDefaultIf matchedName []) - codeOverride state state state - (by simpa [nativeSwitchCaseIfs, Nat.add_assoc, Nat.add_comm, - Nat.add_left_comm] using hCases) - hDefault) +/-- Decode the word-granular payload used by Verity's proof-side log model. -/ +def byteArrayLogWords (bytes : ByteArray) : List Nat := + (List.range (bytes.size / 32)).map (fun i => byteArrayWord bytes (i * 32)) -theorem exec_nativeSwitchPrefix_then_tail_fuel - (fuel : Nat) - (tail : List EvmYul.Yul.Ast.Stmt) +/-- Project native EVMYulLean logs to the current Verity observable event shape: + topics followed by word-aligned log data. -/ +def projectLogEntry (entry : EvmYul.LogEntry) : List Nat := + entry.topics.toList.map uint256ToNat ++ byteArrayLogWords entry.data + +def projectLogsFromState (state : EvmYul.Yul.State) : List (List Nat) := + state.sharedState.substate.logSeries.toList.map projectLogEntry + +@[simp] theorem projectLogEntry_topicsAndWordData + (entry : EvmYul.LogEntry) : + projectLogEntry entry = + entry.topics.toList.map uint256ToNat ++ byteArrayLogWords entry.data := by + rfl + +@[simp] theorem projectLogsFromState_logSeries + (state : EvmYul.Yul.State) : + projectLogsFromState state = + state.sharedState.substate.logSeries.toList.map projectLogEntry := by + rfl + +@[simp] theorem projectLogsFromState_initialState (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (discrName matchedName : EvmYul.Identifier) - (final : EvmYul.Yul.State) - (hTail : - EvmYul.Yul.exec (fuel + 10) (.Block tail) (some contract) - (nativeSwitchPrefixFinalState contract tx storage observableSlots - discrName matchedName) = - .ok final) : - EvmYul.Yul.exec (fuel + 12) - (.Block (nativeSwitchPrefixStmts discrName matchedName ++ tail)) - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .ok final := by - let prefixState := - nativeSwitchPrefixFinalState contract tx storage observableSlots - discrName matchedName - have hPrefix : - EvmYul.Yul.exec (fuel + 12) - (.Block (nativeSwitchPrefixStmts discrName matchedName)) - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .ok prefixState := by - simpa [prefixState, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using - (exec_nativeSwitchPrefix_selector_initialState_ok_fuel fuel - contract tx storage observableSlots discrName matchedName) - exact exec_block_append_ok (fuel + 10) 0 - (nativeSwitchPrefixStmts discrName matchedName) tail - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) - prefixState final - (by simpa [nativeSwitchPrefixStmts, Nat.add_assoc, Nat.add_comm, - Nat.add_left_comm] using hPrefix) - (by simpa [prefixState] using hTail) + (slots : List Nat) : + projectLogsFromState (initialState contract tx storage slots) = [] := by + simp [projectLogsFromState, initialState, EvmYul.Yul.State.sharedState, + YulState.initial, toSharedState, mkBlockHeader] + rfl -theorem exec_nativeSwitchPrefix_then_tail_error_fuel - (fuel : Nat) - (tail : List EvmYul.Yul.Ast.Stmt) +@[simp] theorem projectLogsFromState_nativeSwitchStoreMarkedPrefixStateForId (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (discrName matchedName : EvmYul.Identifier) - (err : EvmYul.Yul.Exception) - (hTail : - EvmYul.Yul.exec (fuel + 10) (.Block tail) (some contract) - (nativeSwitchPrefixFinalState contract tx storage observableSlots - discrName matchedName) = - .error err) : - EvmYul.Yul.exec (fuel + 12) - (.Block (nativeSwitchPrefixStmts discrName matchedName ++ tail)) - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .error err := by - let prefixState := - nativeSwitchPrefixFinalState contract tx storage observableSlots - discrName matchedName - have hPrefix : - EvmYul.Yul.exec (fuel + 12) - (.Block (nativeSwitchPrefixStmts discrName matchedName)) - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .ok prefixState := by - simpa [prefixState, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using - (exec_nativeSwitchPrefix_selector_initialState_ok_fuel fuel - contract tx storage observableSlots discrName matchedName) - exact exec_block_append_error (fuel + 10) 0 - (nativeSwitchPrefixStmts discrName matchedName) tail - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) - prefixState err - (by simpa [nativeSwitchPrefixStmts, Nat.add_assoc, Nat.add_comm, - Nat.add_left_comm] using hPrefix) - (by simpa [prefixState] using hTail) + (slots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) : + projectLogsFromState + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage slots + switchId store) = [] := by + simpa [nativeSwitchStoreMarkedPrefixStateForId, + nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, + EvmYul.Yul.State.insert] using + (projectLogsFromState_initialState contract tx storage slots) + +theorem projectStorageFromState_setStore_ok_left + (tx : YulTransaction) + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (initial : EvmYul.Yul.State) : + projectStorageFromState tx + (((EvmYul.Yul.State.Ok shared store) : EvmYul.Yul.State).setStore + initial) = + projectStorageFromState tx (EvmYul.Yul.State.Ok shared store) := by + funext slot + cases initial <;> + simp [EvmYul.Yul.State.setStore, projectStorageFromState, + EvmYul.Yul.State.sharedState] + +theorem projectLogsFromState_setStore_ok_left + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (initial : EvmYul.Yul.State) : + projectLogsFromState + (((EvmYul.Yul.State.Ok shared store) : EvmYul.Yul.State).setStore + initial) = + projectLogsFromState (EvmYul.Yul.State.Ok shared store) := by + cases initial <;> + simp [EvmYul.Yul.State.setStore, projectLogsFromState, + EvmYul.Yul.State.sharedState] -theorem exec_nativeSwitchTail_find_hit_preserved_fuel - (fuel selector switchId tag : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (defaultBody body : List EvmYul.Yul.Ast.Stmt) - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (final : EvmYul.Yul.State) - (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) (nativeSwitchMarkedPrefixStateForId contract tx storage observableSlots switchId) = .ok final) - (hPreservesMatched : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1) body (some contract)) : - EvmYul.Yul.exec (fuel + cases.length + 10) - (.Block (nativeSwitchTailStmts switchId cases defaultBody)) - (some contract) (nativeSwitchPrefixStateForId contract tx storage observableSlots switchId) = - .ok final := by - let discrName : EvmYul.Identifier := Backends.nativeSwitchDiscrTempName switchId - let matchedName : EvmYul.Identifier := Backends.nativeSwitchMatchedTempName switchId - let prefixState := - nativeSwitchPrefixFinalState contract tx storage observableSlots - discrName matchedName - have hCasesDefault := - exec_nativeSwitchCaseIfs_find_hit_with_default_preserved_fuel - (fuel + 1) selector cases defaultBody tag body (some contract) - prefixState final discrName matchedName hFind - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_matched contract tx storage - observableSlots discrName matchedName)) - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_discr contract tx storage observableSlots - discrName matchedName selector - (nativeSwitchDiscrTempName_ne_matchedTempName switchId) hSelector)) - hSelectorRange hTagsRange - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_marked contract tx storage - observableSlots discrName matchedName)) - (by intro pre suffix hCases; simpa [nativeSwitchMarkedPrefixStateForId, - nativeSwitchPrefixStateForId, prefixState, discrName, matchedName] - using hBody pre suffix hCases) - (by intro pre suffix hCases; simpa [matchedName] using - hPreservesMatched pre suffix hCases) - simpa [nativeSwitchTailStmts, nativeSwitchPrefixStateForId, prefixState, - discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using hCasesDefault +/-- Project a native Yul halt produced by `return`/`stop` to Verity's single-word + return observable. EVMYulLean represents `stop` as `YulHalt _ 0`; `return` + goes through `H_return`, matching the proof oracle's 32-byte return case. -/ +def projectHaltReturn (state : EvmYul.Yul.State) (haltValue : EvmYul.Yul.Ast.Literal) : + Option Nat := + if haltValue = ⟨0⟩ then + none + else if state.sharedState.H_return.size = 32 then + some (byteArrayWord state.sharedState.H_return 0) + else + some 0 + +@[simp] theorem projectHaltReturn_stop + (state : EvmYul.Yul.State) : + projectHaltReturn state ⟨0⟩ = none := by + simp [projectHaltReturn] + +@[simp] theorem projectHaltReturn_32ByteReturn + (state : EvmYul.Yul.State) + (haltValue : EvmYul.Yul.Ast.Literal) + (hHalt : haltValue ≠ ⟨0⟩) + (hSize : state.sharedState.H_return.size = 32) : + projectHaltReturn state haltValue = + some (byteArrayWord state.sharedState.H_return 0) := by + simp [projectHaltReturn, hHalt, hSize] + +/-- Until wider returndata support lands, a non-`stop` halt with a native return + buffer whose size is not exactly one ABI word projects to the conservative + single-word fallback used by the current proof-side observable model. -/ +@[simp] theorem projectHaltReturn_non32ByteReturn + (state : EvmYul.Yul.State) + (haltValue : EvmYul.Yul.Ast.Literal) + (hHalt : haltValue ≠ ⟨0⟩) + (hSize : state.sharedState.H_return.size ≠ 32) : + projectHaltReturn state haltValue = some 0 := by + simp [projectHaltReturn, hHalt, hSize] + +theorem primCall_mstore0_then_return32_emptyMemory_projectHaltReturn + (mstoreFuel returnFuel : Nat) + (sharedState : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (value : EvmYul.UInt256) + (hMemory : sharedState.memory = ByteArray.empty) : + ∃ haltState haltValue, + (do + let (state', values) ← + EvmYul.Yul.primCall (mstoreFuel + 1) (.Ok sharedState store) + EvmYul.Operation.MSTORE + [EvmYul.UInt256.ofNat 0, value] + match values with + | [] => + EvmYul.Yul.primCall (returnFuel + 1) state' + EvmYul.Operation.RETURN + [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + projectHaltReturn haltState haltValue = some value.toNat := by + let state : EvmYul.Yul.State := .Ok sharedState store + let stored := + state.setMachineState + (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value) + let returned := + stored.setMachineState + (stored.toMachineState.evmReturn + (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32)) + refine ⟨returned, ⟨1⟩, ?_⟩ + constructor + · exact primCall_mstore0_then_return32_ok mstoreFuel returnFuel + (.Ok sharedState store) value + · have hHalt : (⟨1⟩ : EvmYul.Yul.Ast.Literal) ≠ ⟨0⟩ := by + intro h + norm_num [EvmYul.UInt256.size] at h + have hSize : returned.sharedState.H_return.size = 32 := by + exact mstore0_then_return32_hReturn_size sharedState store value + have hReturn : returned.sharedState.H_return = value.toByteArray := by + exact mstore0_then_return32_emptyMemory_hReturn_eq_toByteArray + sharedState store value hMemory + rw [projectHaltReturn_32ByteReturn returned ⟨1⟩ hHalt hSize] + rw [hReturn, byteArrayWord_uint256_toByteArray] -/-- Selector-hit switch-tail execution deriving matched-flag preservation from generated freshness. -/ -theorem exec_nativeSwitchTail_find_hit_fresh_fuel - (fuel selector switchId tag : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (defaultBody body : List EvmYul.Yul.Ast.Stmt) - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (final : EvmYul.Yul.State) - (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) (nativeSwitchMarkedPrefixStateForId contract tx storage observableSlots switchId) = .ok final) - (hStmtPreserves : - ∀ stmt, stmt ∈ body → - Backends.nativeSwitchMatchedTempName switchId ∉ - Backends.nativeStmtWriteNames stmt → - NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1) stmt (some contract)) : - EvmYul.Yul.exec (fuel + cases.length + 10) - (.Block (nativeSwitchTailStmts switchId cases defaultBody)) - (some contract) (nativeSwitchPrefixStateForId contract tx storage observableSlots switchId) = - .ok final := by - apply exec_nativeSwitchTail_find_hit_preserved_fuel fuel selector switchId tag - cases defaultBody body contract tx storage observableSlots final hSelector - hFind hSelectorRange hTagsRange hBody - intro pre suffix _hCases - exact NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched - switchId selector tag body defaultBody cases (EvmYul.UInt256.ofNat 1) - (some contract) hFresh hFind hStmtPreserves +/-- The dispatcher-block execution that `EvmYul.Yul.callDispatcher` performs + after its initial fuel check and empty-argument call-frame setup. -theorem exec_nativeSwitchTail_find_hit_error_fuel - (fuel selector switchId tag : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody body : List EvmYul.Yul.Ast.Stmt) +Keeping this expression named lets the native/EVMYulLean bridge target +statement execution of the lowered dispatcher body directly, instead of +re-opening the full `callDispatcher` wrapper at each EndToEnd proof site. -/ +def callDispatcherBlockResult + (fuel' : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (err : EvmYul.Yul.Exception) - (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) (nativeSwitchMarkedPrefixStateForId contract tx storage observableSlots switchId) = .error err) : - EvmYul.Yul.exec (fuel + cases.length + 10) - (.Block (nativeSwitchTailStmts switchId cases defaultBody)) - (some contract) (nativeSwitchPrefixStateForId contract tx storage observableSlots switchId) = - .error err := by - let discrName : EvmYul.Identifier := Backends.nativeSwitchDiscrTempName switchId - let matchedName : EvmYul.Identifier := Backends.nativeSwitchMatchedTempName switchId - let prefixState := - nativeSwitchPrefixFinalState contract tx storage observableSlots - discrName matchedName - have hCasesDefault := - exec_nativeSwitchCaseIfs_find_hit_with_default_error_fuel - (fuel + 1) selector cases defaultBody tag body (some contract) - prefixState discrName matchedName err hFind - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_matched contract tx storage - observableSlots discrName matchedName)) - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_discr contract tx storage observableSlots - discrName matchedName selector - (nativeSwitchDiscrTempName_ne_matchedTempName switchId) hSelector)) - hSelectorRange hTagsRange - (by intro pre suffix hCases; simpa [nativeSwitchMarkedPrefixStateForId, - nativeSwitchPrefixStateForId, prefixState, discrName, matchedName] - using hBody pre suffix hCases) - simpa [nativeSwitchTailStmts, nativeSwitchPrefixStateForId, prefixState, - discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using hCasesDefault + (initial : EvmYul.Yul.State) : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := + let dispatcherDef := + EvmYul.Yul.Ast.FunctionDefinition.Def [] [] + [initial.executionEnv.code.dispatcher] + let callState := EvmYul.Yul.State.mkOk (initial.initcall dispatcherDef.params []) + match EvmYul.Yul.exec fuel' (.Block dispatcherDef.body) (some contract) callState with + | .error err => .error err + | .ok finalState => + let restored := finalState.reviveJump.overwrite? initial |>.setStore initial + .ok (restored, List.map finalState.lookup! dispatcherDef.rets) -theorem exec_nativeSwitchTail_find_none_with_default_nonempty_fuel - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) +/-- Dispatcher-block execution specialized to the lowered contract dispatcher + rather than the state-installed dispatcher lookup. + +For states built by `initialState`, this is definitionally the next proof +target after `callDispatcherBlockResult`: native execution of the lowered +contract's dispatcher statement. -/ +def contractDispatcherBlockResult + (fuel' : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (initial : EvmYul.Yul.State) : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := + let dispatcherDef := + EvmYul.Yul.Ast.FunctionDefinition.Def [] [] [contract.dispatcher] + let callState := EvmYul.Yul.State.mkOk (initial.initcall dispatcherDef.params []) + match EvmYul.Yul.exec fuel' (.Block dispatcherDef.body) (some contract) callState with + | .error err => .error err + | .ok finalState => + let restored := finalState.reviveJump.overwrite? initial |>.setStore initial + .ok (restored, List.map finalState.lookup! dispatcherDef.rets) + +/-- Raw native execution of the lowered contract dispatcher block, before the + `callDispatcher`-style state restoration and return-list projection. -/ +def contractDispatcherExecResult + (fuel' : Nat) (contract : EvmYul.Yul.Ast.YulContract) + (initial : EvmYul.Yul.State) : + Except EvmYul.Yul.Exception EvmYul.Yul.State := + let dispatcherDef := + EvmYul.Yul.Ast.FunctionDefinition.Def [] [] [contract.dispatcher] + let callState := EvmYul.Yul.State.mkOk (initial.initcall dispatcherDef.params []) + EvmYul.Yul.exec fuel' (.Block dispatcherDef.body) (some contract) callState + +/-- Executing a singleton block whose only statement is another block is the + same as executing the inner block, after the outer block consumes its fuel + step. This is the structural wrapper around lowered contract dispatchers: + `contractDispatcherExecResult` installs `[contract.dispatcher]` as the + function body, while generated dispatcher lemmas reason about the lowered + block itself. -/ +theorem exec_singleton_block_eq_exec_block + (fuel : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (codeOverride : Option EvmYul.Yul.Ast.YulContract) + (state : EvmYul.Yul.State) : + EvmYul.Yul.exec (Nat.succ (Nat.succ fuel)) (.Block [.Block body]) + codeOverride state = + EvmYul.Yul.exec (Nat.succ fuel) (.Block body) codeOverride state := by + simp [EvmYul.Yul.exec] + cases EvmYul.Yul.exec (Nat.succ fuel) (.Block body) codeOverride state <;> + simp + +/-- Raw dispatcher execution for a lowered contract whose dispatcher is already + a block reduces to direct execution of that block from the native initial + switch state. This removes the function-call-frame wrapper from later + SimpleStorage dispatcher case proofs. -/ +theorem contractDispatcherExecResult_block_dispatcher_eq_exec_block + (fuel : Nat) + (body : List EvmYul.Yul.Ast.Stmt) + (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (final : EvmYul.Yul.State) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = none) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) - (hDefaultBody : - EvmYul.Yul.exec ((fuel + 1) + 7) (.Block defaultBody) (some contract) - (nativeSwitchPrefixStateForId contract tx storage observableSlots - switchId) = .ok final) - (hNonempty : defaultBody ≠ []) : - EvmYul.Yul.exec (fuel + cases.length + 10) - (.Block (nativeSwitchTailStmts switchId cases defaultBody)) - (some contract) (nativeSwitchPrefixStateForId contract tx storage - observableSlots switchId) = - .ok final := by - let discrName : EvmYul.Identifier := Backends.nativeSwitchDiscrTempName switchId - let matchedName : EvmYul.Identifier := Backends.nativeSwitchMatchedTempName switchId - let prefixState := - nativeSwitchPrefixFinalState contract tx storage observableSlots - discrName matchedName - have hCasesDefault := - exec_nativeSwitchCaseIfs_find_none_with_default_nonempty_fuel - (fuel + 1) selector cases defaultBody (some contract) - prefixState final discrName matchedName hFind - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_matched contract tx storage - observableSlots discrName matchedName)) - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_discr contract tx storage observableSlots - discrName matchedName selector - (nativeSwitchDiscrTempName_ne_matchedTempName switchId) hSelector)) - hSelectorRange hTagsRange - (by simpa [nativeSwitchPrefixStateForId, prefixState, discrName, - matchedName] using hDefaultBody) - hNonempty - simpa [nativeSwitchTailStmts, nativeSwitchPrefixStateForId, prefixState, - discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using hCasesDefault + (observableSlots : List Nat) : + contractDispatcherExecResult (Nat.succ (Nat.succ fuel)) + { dispatcher := .Block body, functions := functions } + (initialState { dispatcher := .Block body, functions := functions } tx + storage observableSlots) = + EvmYul.Yul.exec (Nat.succ fuel) (.Block body) + (some { dispatcher := .Block body, functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block body, functions := functions } tx storage + observableSlots) := by + have hCallState : + EvmYul.Yul.State.mkOk + ((initialState { dispatcher := .Block body, functions := functions } tx + storage observableSlots).initcall [] []) = + nativeSwitchInitialOkState + { dispatcher := .Block body, functions := functions } tx storage + observableSlots := by + simp [nativeSwitchInitialOkState, initialState, EvmYul.Yul.State.initcall, + EvmYul.Yul.State.setStore, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.mkOk] + constructor <;> rfl + unfold contractDispatcherExecResult + change + EvmYul.Yul.exec (Nat.succ (Nat.succ fuel)) (.Block [.Block body]) + (some { dispatcher := .Block body, functions := functions }) + (EvmYul.Yul.State.mkOk + ((initialState { dispatcher := .Block body, functions := functions } tx + storage observableSlots).initcall [] [])) = + EvmYul.Yul.exec (Nat.succ fuel) (.Block body) + (some { dispatcher := .Block body, functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block body, functions := functions } tx storage + observableSlots) + rw [hCallState] + exact exec_singleton_block_eq_exec_block fuel body + (some { dispatcher := .Block body, functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block body, functions := functions } tx storage + observableSlots) + +/-- The projected dispatcher-block result is just raw lowered-dispatcher + execution followed by the same restoration/projection used by + `callDispatcher`. -/ +theorem contractDispatcherBlockResult_eq_execResult + (fuel' : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (initial : EvmYul.Yul.State) : + contractDispatcherBlockResult fuel' contract initial = + let dispatcherDef := + EvmYul.Yul.Ast.FunctionDefinition.Def [] [] [contract.dispatcher] + match contractDispatcherExecResult fuel' contract initial with + | .error err => .error err + | .ok finalState => + let restored := finalState.reviveJump.overwrite? initial |>.setStore initial + .ok (restored, List.map finalState.lookup! dispatcherDef.rets) := by + simp [contractDispatcherBlockResult, contractDispatcherExecResult] -theorem exec_nativeSwitchTail_find_none_without_default_fuel - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) +/-- `initialState` installs the lowered contract as the execution contract, so + the dispatcher-block target can be rewritten to the lowered contract's own + dispatcher. -/ +theorem callDispatcherBlockResult_initialState_eq_contractDispatcherBlockResult + (fuel' : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = none) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : - EvmYul.Yul.exec (fuel + cases.length + 10) - (.Block (nativeSwitchTailStmts switchId cases [])) - (some contract) (nativeSwitchPrefixStateForId contract tx storage - observableSlots switchId) = - .ok (nativeSwitchPrefixStateForId contract tx storage observableSlots - switchId) := by - let discrName : EvmYul.Identifier := Backends.nativeSwitchDiscrTempName switchId - let matchedName : EvmYul.Identifier := Backends.nativeSwitchMatchedTempName switchId - let prefixState := - nativeSwitchPrefixFinalState contract tx storage observableSlots - discrName matchedName - have hCasesDefault := - exec_nativeSwitchCaseIfs_find_none_without_default_fuel - (fuel + 1) selector cases (some contract) - prefixState discrName matchedName hFind - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_matched contract tx storage - observableSlots discrName matchedName)) - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_discr contract tx storage observableSlots - discrName matchedName selector - (nativeSwitchDiscrTempName_ne_matchedTempName switchId) hSelector)) - hSelectorRange hTagsRange - simpa [nativeSwitchTailStmts, nativeSwitchPrefixStateForId, prefixState, - discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using hCasesDefault + (observableSlots : List Nat) : + callDispatcherBlockResult fuel' contract + (initialState contract tx storage observableSlots) = + contractDispatcherBlockResult fuel' contract + (initialState contract tx storage observableSlots) := by + have hcode : + (initialState contract tx storage observableSlots).executionEnv.code = + contract := by + simp [initialState, EvmYul.Yul.State.executionEnv] + simp [callDispatcherBlockResult, contractDispatcherBlockResult, hcode] -/-- Selector-miss execution for a lowered switch tail with the compiler's - generated `revert(0, 0)` default. This carries the guarded miss proof from - the case-chain level to the switch-tail shape used by lowered dispatchers. -/ -theorem exec_nativeSwitchTail_find_none_with_revert_default_fuel - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) +@[simp] theorem callDispatcher_zero (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = none) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : - EvmYul.Yul.exec (fuel + cases.length + 10) - (.Block (nativeSwitchTailStmts switchId cases [nativeRevertZeroZeroStmt])) - (some contract) (nativeSwitchPrefixStateForId contract tx storage - observableSlots switchId) = - .error EvmYul.Yul.Exception.Revert := by - let discrName : EvmYul.Identifier := Backends.nativeSwitchDiscrTempName switchId - let matchedName : EvmYul.Identifier := Backends.nativeSwitchMatchedTempName switchId - let prefixState := - nativeSwitchPrefixFinalState contract tx storage observableSlots - discrName matchedName - have hCasesDefault := - exec_nativeSwitchCaseIfs_find_none_with_revert_default_fuel - (fuel + 1) selector cases (some contract) - prefixState discrName matchedName hFind - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_matched contract tx storage - observableSlots discrName matchedName)) - (by simpa [prefixState, discrName, matchedName] using - (nativeSwitchPrefixFinalState_discr contract tx storage observableSlots - discrName matchedName selector - (nativeSwitchDiscrTempName_ne_matchedTempName switchId) hSelector)) - hSelectorRange hTagsRange - simpa [nativeSwitchTailStmts, nativeSwitchPrefixStateForId, prefixState, - discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] - using hCasesDefault + (initial : EvmYul.Yul.State) : + EvmYul.Yul.callDispatcher 0 (some contract) initial = + .error EvmYul.Yul.Exception.OutOfFuel := by + simp [EvmYul.Yul.callDispatcher] -theorem exec_lowerNativeSwitchBlock_selector_find_hit_preserved_fuel - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) - (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) +/-- `callDispatcher` is exactly execution of the installed dispatcher block + once fuel and call-frame setup have been peeled away. -/ +theorem callDispatcher_succ_eq_callDispatcherBlockResult + (fuel' : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (final : EvmYul.Yul.State) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) - ((nativeSwitchPrefixFinalState contract tx storage observableSlots - (Backends.nativeSwitchDiscrTempName switchId) - (Backends.nativeSwitchMatchedTempName switchId)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1)) = .ok final) - (hPreservesMatched : ∀ pre suffix, - cases = pre ++ (tag, body) :: suffix → - NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1) body (some contract)) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (initial : EvmYul.Yul.State) : + EvmYul.Yul.callDispatcher (Nat.succ fuel') (some contract) initial = + callDispatcherBlockResult fuel' contract initial := by + simp [EvmYul.Yul.callDispatcher, callDispatcherBlockResult] + cases + EvmYul.Yul.exec fuel' + (.Block + (EvmYul.Yul.Ast.FunctionDefinition.Def [] [] + [initial.executionEnv.code.dispatcher]).body) (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .ok final := by - rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] - apply exec_nativeSwitchPrefix_then_tail_fuel - exact exec_nativeSwitchTail_find_hit_preserved_fuel fuel selector switchId tag - cases defaultBody body contract tx storage observableSlots final - hSelector hFind hSelectorRange hTagsRange hBody hPreservesMatched + (EvmYul.Yul.State.mkOk + (initial.initcall + (EvmYul.Yul.Ast.FunctionDefinition.Def [] [] + [initial.executionEnv.code.dispatcher]).params [])) <;> rfl -theorem exec_lowerNativeSwitchBlock_selector_find_hit_fresh_fuel - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) - (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) +/-- Convert a native `callDispatcher` result to the current Verity observable + result shape. Reverts and hard native errors conservatively roll storage + back to the supplied initial storage function. -/ +def projectResult + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (result : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal)) : + YulResult := + match result with + | .ok (state, values) => + let finalStorage := projectStorageFromState tx state + { success := true + returnValue := values.head?.map uint256ToNat + finalStorage := finalStorage + finalMappings := Compiler.Proofs.storageAsMappings finalStorage + events := initialEvents ++ projectLogsFromState state } + | .error (.YulHalt state value) => + let finalStorage := projectStorageFromState tx state + { success := true + returnValue := projectHaltReturn state value + finalStorage := finalStorage + finalMappings := Compiler.Proofs.storageAsMappings finalStorage + events := initialEvents ++ projectLogsFromState state } + | .error _ => + { success := false + returnValue := none + finalStorage := initialStorage + finalMappings := Compiler.Proofs.storageAsMappings initialStorage + events := initialEvents } + +@[simp] theorem projectResult_ok + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (values : List EvmYul.Yul.Ast.Literal) : + projectResult tx initialStorage initialEvents (.ok (state, values)) = + { success := true + returnValue := values.head?.map uint256ToNat + finalStorage := projectStorageFromState tx state + finalMappings := + Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) + events := initialEvents ++ projectLogsFromState state } := by + rfl + +theorem projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_success (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (final : EvmYul.Yul.State) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) - ((nativeSwitchPrefixFinalState contract tx storage observableSlots - (Backends.nativeSwitchDiscrTempName switchId) - (Backends.nativeSwitchMatchedTempName switchId)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1)) = .ok final) - (hStmtPreserves : - ∀ stmt, stmt ∈ body → - Backends.nativeSwitchMatchedTempName switchId ∉ - Backends.nativeStmtWriteNames stmt → - NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1) stmt (some contract)) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .ok final := by - rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] - apply exec_nativeSwitchPrefix_then_tail_fuel - exact exec_nativeSwitchTail_find_hit_fresh_fuel fuel selector switchId tag - cases defaultBody body contract tx storage observableSlots final hSelector - hFind hSelectorRange hTagsRange hFresh hBody hStmtPreserves + (initialEvents : List (List Nat)) + (slots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) : + (projectResult tx storage initialEvents + (.ok + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage slots + switchId store, []))).success = true := by + rfl -theorem exec_lowerNativeSwitchBlock_selector_find_hit_error_fuel - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) - (tag : Nat) - (body : List EvmYul.Yul.Ast.Stmt) +theorem projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_returnValue (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (err : EvmYul.Yul.Exception) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) - ((nativeSwitchPrefixFinalState contract tx storage observableSlots - (Backends.nativeSwitchDiscrTempName switchId) - (Backends.nativeSwitchMatchedTempName switchId)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1)) = .error err) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .error err := by - rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] - apply exec_nativeSwitchPrefix_then_tail_error_fuel - exact exec_nativeSwitchTail_find_hit_error_fuel fuel selector switchId tag - cases defaultBody body contract tx storage observableSlots err - hSelector hFind hSelectorRange hTagsRange hBody + (initialEvents : List (List Nat)) + (slots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) : + (projectResult tx storage initialEvents + (.ok + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage slots + switchId store, []))).returnValue = none := by + rfl -theorem exec_lowerNativeSwitchBlock_selector_find_none_with_default_nonempty_fuel - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) +theorem projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_events (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (final : EvmYul.Yul.State) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = none) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) - (hDefaultBody : - EvmYul.Yul.exec ((fuel + 1) + 7) (.Block defaultBody) (some contract) - (nativeSwitchPrefixFinalState contract tx storage observableSlots - (Backends.nativeSwitchDiscrTempName switchId) - (Backends.nativeSwitchMatchedTempName switchId)) = - .ok final) - (hNonempty : defaultBody ≠ []) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .ok final := by - rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] - apply exec_nativeSwitchPrefix_then_tail_fuel - exact exec_nativeSwitchTail_find_none_with_default_nonempty_fuel fuel - selector switchId cases defaultBody contract tx storage observableSlots - final hSelector hFind hSelectorRange hTagsRange hDefaultBody hNonempty + (initialEvents : List (List Nat)) + (slots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) : + (projectResult tx storage initialEvents + (.ok + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage slots + switchId store, []))).events = initialEvents := by + change initialEvents ++ projectLogsFromState + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage slots + switchId store) = initialEvents + rw [projectLogsFromState_nativeSwitchStoreMarkedPrefixStateForId] + simp -/-- Guarded selector-miss execution for a fully lowered native switch block - whose generated default is `revert(0, 0)`. This discharges the generic - default-body premise with the actual native `REVERT` primitive path at the - same lowered-block boundary used by dispatcher proofs. -/ -theorem exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_fuel - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) +theorem projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_storageSlot + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (slots : List Nat) + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (slot : Nat) + (hSlot : slot ∈ slots) : + (projectResult tx storage initialEvents + (.ok + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage slots + switchId store, []))).finalStorage (IRStorageSlot.ofNat slot) = + storage (IRStorageSlot.ofNat slot) := by + simpa [projectResult] using + (nativeSwitchStoreMarkedPrefixStateForId_materializedStorageSlot contract tx + storage slots switchId store slot hSlot) + +theorem projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_observableStorageSlot (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (runtimeCode : List YulStmt) (observableSlots : List Nat) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = none) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases - [nativeRevertZeroZeroStmt]) - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .error EvmYul.Yul.Exception.Revert := by - rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] - apply exec_nativeSwitchPrefix_then_tail_error_fuel - exact exec_nativeSwitchTail_find_none_with_revert_default_fuel fuel selector - switchId cases contract tx storage observableSlots hSelector hFind - hSelectorRange hTagsRange + (switchId : Nat) + (store : EvmYul.Yul.VarStore) + (slot : Nat) + (hSlot : slot ∈ observableSlots) : + (projectResult tx storage initialEvents + (.ok + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + (materializedStorageSlots runtimeCode observableSlots) + switchId store, []))).finalStorage (IRStorageSlot.ofNat slot) = + storage (IRStorageSlot.ofNat slot) := by + exact + projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_storageSlot + contract tx storage initialEvents + (materializedStorageSlots runtimeCode observableSlots) switchId store slot + (observableSlot_mem_materializedStorageSlots runtimeCode observableSlots + slot hSlot) -/-- Store-parametric prefix-then-tail-error glue for `lowerNativeSwitchBlock`. - Given the tail body errors on the post-prefix state extended over an - arbitrary preceding native varstore, the full lowered switch block errors - on the matching state with that store. Together with the store-parametric - prefix lemma `exec_nativeSwitchPrefix_selector_initialState_store_ok_fuel`, - this lifts switch-block error proofs to states already carrying additional - bindings (e.g. the buildSwitch wrapper's `__has_selector := 1`). -/ -theorem exec_lowerNativeSwitchBlock_storePrefix_tail_error_fuel - (fuel switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) +theorem projectResult_ok_setStore_ok_left + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (err : EvmYul.Yul.Exception) - (hTail : - EvmYul.Yul.exec (fuel + 10) - (.Block (nativeSwitchTailStmts switchId cases defaultBody)) - (some contract) - (((.Ok (initialState contract tx storage observableSlots).sharedState store - : EvmYul.Yul.State).insert - (Backends.nativeSwitchDiscrTempName switchId) - (EvmYul.UInt256.ofNat - (tx.functionSelector % Compiler.Constants.selectorModulus))).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 0)) = - .error err) : - EvmYul.Yul.exec (fuel + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) - (some contract) - (.Ok (initialState contract tx storage observableSlots).sharedState store) = - .error err := by - let discrName := Backends.nativeSwitchDiscrTempName switchId - let matchedName := Backends.nativeSwitchMatchedTempName switchId - let initState : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - let prefixState : EvmYul.Yul.State := - (initState.insert discrName - (EvmYul.UInt256.ofNat - (tx.functionSelector % Compiler.Constants.selectorModulus))).insert - matchedName (EvmYul.UInt256.ofNat 0) - rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] - apply exec_block_append_error (fuel + 10) 0 - (nativeSwitchPrefixStmts discrName matchedName) - (nativeSwitchTailStmts switchId cases defaultBody) - (some contract) initState prefixState err - · simpa [nativeSwitchPrefixStmts, prefixState, initState, Nat.add_assoc, - Nat.add_comm, Nat.add_left_comm] using - exec_nativeSwitchPrefix_selector_initialState_store_ok_fuel - fuel contract tx storage observableSlots store discrName matchedName - · simpa [prefixState, initState] using hTail + (initial : EvmYul.Yul.State) + (values : List EvmYul.Yul.Ast.Literal) : + projectResult tx initialStorage initialEvents + (.ok + ((((EvmYul.Yul.State.Ok shared store) : EvmYul.Yul.State).setStore + initial), values)) = + projectResult tx initialStorage initialEvents + (.ok (EvmYul.Yul.State.Ok shared store, values)) := by + cases initial <;> + simp [projectResult, EvmYul.Yul.State.setStore, projectStorageFromState, + EvmYul.Yul.State.sharedState, projectLogsFromState] -def nativeSwitchStoreInitialState - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store +theorem projectResult_ok_restoreCallFrame_of_reviveJump_ok + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (final initial : EvmYul.Yul.State) + (values : List EvmYul.Yul.Ast.Literal) + (shared : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (hRevive : + final.reviveJump = EvmYul.Yul.State.Ok shared store) + (hInitialOk : + ∃ initialShared initialStore, + initial = EvmYul.Yul.State.Ok initialShared initialStore) : + projectResult tx initialStorage initialEvents + (.ok (((final.reviveJump.overwrite? initial).setStore initial), values)) = + projectResult tx initialStorage initialEvents + (.ok (final.reviveJump, values)) := by + rcases hInitialOk with ⟨initialShared, initialStore, rfl⟩ + rw [hRevive] + simpa [EvmYul.Yul.State.overwrite?] using + (projectResult_ok_setStore_ok_left tx initialStorage initialEvents shared + store (EvmYul.Yul.State.Ok initialShared initialStore) values) -def nativeSwitchStorePrefixStateForId - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (switchId : Nat) (store : EvmYul.Yul.VarStore) : EvmYul.Yul.State := - ((nativeSwitchStoreInitialState contract tx storage observableSlots store).insert - (Backends.nativeSwitchDiscrTempName switchId) - (EvmYul.UInt256.ofNat - (tx.functionSelector % Compiler.Constants.selectorModulus))).insert - (Backends.nativeSwitchMatchedTempName switchId) (EvmYul.UInt256.ofNat 0) +/-- Exact projected result for native primitive execution of + `sstore(slot, value)` from an initial runtime shared state and arbitrary + dispatcher local-variable store. + +This is the generic word-canonical `SSTORE` primitive result shape needed by +the dispatcher proof before the SimpleStorage setter composes it with +`CALLDATALOAD` and `STOP`. -/ +theorem primCall_sstore_initialState_wordSlot_withStore_projectResult_eq + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (slot value : Nat) + (hSlotRange : slot < EvmYul.UInt256.size) : + ∃ finalState, + EvmYul.Yul.primCall (fuel + 1) + (.Ok (initialState contract tx storage observableSlots).sharedState store) + EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = + .ok (finalState, []) ∧ + projectResult tx storage initialEvents (.ok (finalState, [])) = + { success := true + returnValue := none + finalStorage := projectStorageFromState tx finalState + finalMappings := + Compiler.Proofs.storageAsMappings (projectStorageFromState tx finalState) + events := initialEvents ++ projectLogsFromState finalState } := by + let initialWithStore : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + refine ⟨initialWithStore.setState + (initialWithStore.toState.sstore (natToUInt256 slot) (natToUInt256 value)), + ?_, ?_⟩ + · exact primCall_sstore_initialState_wordSlot_ok_withStore fuel contract tx + storage observableSlots store slot value hSlotRange + · simp [projectResult] + +@[simp] theorem projectResult_yulHalt + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (value : EvmYul.Yul.Ast.Literal) : + projectResult tx initialStorage initialEvents + (.error (.YulHalt state value)) = + { success := true + returnValue := projectHaltReturn state value + finalStorage := projectStorageFromState tx state + finalMappings := + Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) + events := initialEvents ++ projectLogsFromState state } := by + rfl -def nativeSwitchStoreMarkedPrefixStateForId - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (switchId : Nat) (store : EvmYul.Yul.VarStore) : EvmYul.Yul.State := - (nativeSwitchStorePrefixStateForId contract tx storage observableSlots - switchId store).insert - (Backends.nativeSwitchMatchedTempName switchId) (EvmYul.UInt256.ofNat 1) +@[simp] theorem projectResult_ok_events + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (values : List EvmYul.Yul.Ast.Literal) : + (projectResult tx initialStorage initialEvents (.ok (state, values))).events = + initialEvents ++ projectLogsFromState state := by + rfl -def nativeSwitchHasSelectorStore : EvmYul.Yul.VarStore := - (∅ : EvmYul.Yul.VarStore).insert "__has_selector" (EvmYul.UInt256.ofNat 1) +@[simp] theorem projectResult_ok_success + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (values : List EvmYul.Yul.Ast.Literal) : + (projectResult tx initialStorage initialEvents + (.ok (state, values))).success = true := by + rfl -def nativeSwitchHasSelectorInitialState - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) : EvmYul.Yul.State := - nativeSwitchStoreInitialState contract tx storage observableSlots - nativeSwitchHasSelectorStore +@[simp] theorem projectResult_ok_returnValue + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (values : List EvmYul.Yul.Ast.Literal) : + (projectResult tx initialStorage initialEvents + (.ok (state, values))).returnValue = + values.head?.map uint256ToNat := by + rfl -theorem nativeSwitchInitialOkState_insert_hasSelector_eq - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) : - (nativeSwitchInitialOkState contract tx storage observableSlots).insert - "__has_selector" (EvmYul.UInt256.ofNat 1) = - nativeSwitchHasSelectorInitialState contract tx storage observableSlots := by - simp [nativeSwitchInitialOkState, nativeSwitchHasSelectorInitialState, - nativeSwitchStoreInitialState, nativeSwitchHasSelectorStore, - EvmYul.Yul.State.insert] +@[simp] theorem projectResult_ok_finalMappings + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (values : List EvmYul.Yul.Ast.Literal) : + (projectResult tx initialStorage initialEvents + (.ok (state, values))).finalMappings = + Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) := by + rfl -/-- `matched := 0` lookup on the post-prefix state with arbitrary store. -/ -theorem nativeSwitchPrefixStoreState_matched_eq - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (discrName matchedName : EvmYul.Identifier) - (discrValue : EvmYul.Literal) : - (((.Ok (initialState contract tx storage observableSlots).sharedState store - : EvmYul.Yul.State).insert discrName discrValue).insert - matchedName (EvmYul.UInt256.ofNat 0))[matchedName]! = - EvmYul.UInt256.ofNat 0 := by - simp [EvmYul.Yul.State.insert, GetElem?.getElem!, decidableGetElem?, - GetElem.getElem, EvmYul.Yul.State.store, EvmYul.Yul.State.lookup!] +@[simp] theorem projectResult_ok_finalStorageSlot + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (values : List EvmYul.Yul.Ast.Literal) + (slot : Nat) + (account : EvmYul.Account .Yul) + (value : EvmYul.UInt256) + (hAccount : + state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = + some account) + (hSlot : account.storage.find? (natToUInt256 slot) = some value) : + (projectResult tx initialStorage initialEvents + (.ok (state, values))).finalStorage (IRStorageSlot.ofNat slot) = value := by + simp [projectResult, projectStorageFromState_accountStorageSlot, + hAccount, hSlot] -/-- `discr := selector` lookup on the post-prefix state with arbitrary store. -/ -theorem nativeSwitchPrefixStoreState_discr_eq - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (discrName matchedName : EvmYul.Identifier) - (selector : Nat) (hne : discrName ≠ matchedName) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) : - (((.Ok (initialState contract tx storage observableSlots).sharedState store - : EvmYul.Yul.State).insert discrName - (EvmYul.UInt256.ofNat - (tx.functionSelector % Compiler.Constants.selectorModulus))).insert - matchedName (EvmYul.UInt256.ofNat 0))[discrName]! = - EvmYul.UInt256.ofNat selector := by - rw [hSelector] - simp [EvmYul.Yul.State.insert, GetElem?.getElem!, decidableGetElem?, - GetElem.getElem, EvmYul.Yul.State.store, EvmYul.Yul.State.lookup!] - rw [Finmap.lookup_insert_of_ne] - · rw [Finmap.lookup_insert]; simp - · exact hne +@[simp] theorem projectResult_ok_missingFinalStorageAccountSlot + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (values : List EvmYul.Yul.Ast.Literal) + (slot : Nat) + (hAccount : + state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = + none) : + (projectResult tx initialStorage initialEvents + (.ok (state, values))).finalStorage (IRStorageSlot.ofNat slot) = 0 := by + simp [projectResult, projectStorageFromState_missingAccount, hAccount] -/-- Store-parametric prefix-then-tail-ok glue for `lowerNativeSwitchBlock`. - This is the success dual of - `exec_lowerNativeSwitchBlock_storePrefix_tail_error_fuel`: it lifts switch - tail proofs to states already carrying additional bindings while preserving - the final state returned by the tail. -/ -theorem exec_lowerNativeSwitchBlock_storePrefix_tail_ok_fuel - (fuel switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody : List EvmYul.Yul.Ast.Stmt) - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (final : EvmYul.Yul.State) - (hTail : - EvmYul.Yul.exec (fuel + 10) - (.Block (nativeSwitchTailStmts switchId cases defaultBody)) - (some contract) - (nativeSwitchStorePrefixStateForId contract tx storage observableSlots - switchId store) = .ok final) : - EvmYul.Yul.exec (fuel + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) - (some contract) - (nativeSwitchStoreInitialState contract tx storage observableSlots store) = - .ok final := by - let discrName := Backends.nativeSwitchDiscrTempName switchId - let matchedName := Backends.nativeSwitchMatchedTempName switchId - let initState := - nativeSwitchStoreInitialState contract tx storage observableSlots store - let prefixState := - nativeSwitchStorePrefixStateForId contract tx storage observableSlots - switchId store - rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] - apply exec_block_append_ok (fuel + 10) 0 - (nativeSwitchPrefixStmts discrName matchedName) - (nativeSwitchTailStmts switchId cases defaultBody) - (some contract) initState prefixState final - · simpa [nativeSwitchPrefixStmts, prefixState, initState, Nat.add_assoc, - Nat.add_comm, Nat.add_left_comm, nativeSwitchStorePrefixStateForId, - nativeSwitchStoreInitialState, discrName, matchedName] using - exec_nativeSwitchPrefix_selector_initialState_store_ok_fuel - fuel contract tx storage observableSlots store discrName matchedName - · simpa [prefixState, initState] using hTail +@[simp] theorem projectResult_ok_missingFinalStorageSlot + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (values : List EvmYul.Yul.Ast.Literal) + (slot : Nat) + (account : EvmYul.Account .Yul) + (hAccount : + state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = + some account) + (hSlot : account.storage.find? (natToUInt256 slot) = none) : + (projectResult tx initialStorage initialEvents + (.ok (state, values))).finalStorage (IRStorageSlot.ofNat slot) = 0 := by + simp [projectResult, projectStorageFromState_missingAccountStorageSlot, + hAccount, hSlot] -/-- Store-parametric guarded selector-hit execution for the lowered switch - block. This is the success dual of - `exec_lowerNativeSwitchBlock_selector_find_hit_error_store_fuel`, retaining - the matched-flag preservation premise needed to skip the generated default - after a successful selected body. -/ -theorem exec_lowerNativeSwitchBlock_selector_find_hit_preserved_store_fuel - (fuel selector switchId tag : Nat) (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody body : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) (final : EvmYul.Yul.State) - (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx storage observableSlots switchId store) = .ok final) - (hPreservesMatched : ∀ pre suffix, - cases = pre ++ (tag, body) :: suffix → - NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) (EvmYul.UInt256.ofNat 1) - body (some contract)) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) (some contract) - (nativeSwitchStoreInitialState contract tx storage observableSlots store) = - .ok final := by - let discrName := Backends.nativeSwitchDiscrTempName switchId - let matchedName := Backends.nativeSwitchMatchedTempName switchId - have hne := nativeSwitchDiscrTempName_ne_matchedTempName switchId - have hCases := - exec_nativeSwitchCaseIfs_find_hit_with_default_preserved_fuel - (fuel + 1) selector cases defaultBody tag body (some contract) _ - final discrName matchedName hFind - (nativeSwitchPrefixStoreState_matched_eq contract tx storage - observableSlots store discrName matchedName _) - (nativeSwitchPrefixStoreState_discr_eq contract tx storage - observableSlots store discrName matchedName selector hne hSelector) - hSelectorRange hTagsRange - (by - simp [EvmYul.Yul.State.insert, GetElem?.getElem!, - decidableGetElem?, GetElem.getElem, EvmYul.Yul.State.store, - EvmYul.Yul.State.lookup!]) - hBody - (by intro pre suffix hCases; simpa [matchedName] using - hPreservesMatched pre suffix hCases) - exact exec_lowerNativeSwitchBlock_storePrefix_tail_ok_fuel - (fuel + cases.length) switchId cases defaultBody contract tx storage - observableSlots store final (by - simpa [nativeSwitchTailStmts, discrName, matchedName, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm, - nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, - nativeSwitchStoreMarkedPrefixStateForId] using hCases) +/-- Native primitive execution of `sstore(slot, value)` on a word-canonical + initial runtime slot, lifted through Verity's projected native result + boundary for a nonzero write. + +This is the generic storage-projection form of the SimpleStorage slot-zero +setter lemma: it proves that the actual EVMYulLean `SSTORE` primitive writes +the projected final storage word for any canonical slot, as long as the EVM +storage update takes the insertion branch rather than the zero-value erasure +branch. -/ +theorem primCall_sstore_initialState_wordSlot_projectResult_slot + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (slot value : Nat) + (hSlotRange : slot < EvmYul.UInt256.size) + (hValueNonzero : + (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = false) : + ∃ finalState, + EvmYul.Yul.primCall (fuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = + .ok (finalState, []) ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = + natToUInt256 value := by + refine ⟨(initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (natToUInt256 slot) (natToUInt256 value)), ?_, ?_⟩ + · exact primCall_sstore_initialState_wordSlot_ok fuel contract tx storage + observableSlots slot value hSlotRange + · simp only [projectResult, projectStorageFromState, extractStorage, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, YulState.initial, toSharedState] + have hBranch : + (EvmYul.UInt256.ofNat value == (Inhabited.default : EvmYul.UInt256)) = + false := by + simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueNonzero + rw [hBranch] + simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ + Std.ReflCmp.compare_self] -/-- Store-parametric selector-hit success derived from generated native switch - freshness. This removes the explicit matched-flag preservation premise for - selected bodies when the generated freshness predicate proves the body does - not write the matched temp. -/ -theorem exec_lowerNativeSwitchBlock_selector_find_hit_fresh_store_fuel - (fuel selector switchId tag : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody body : List EvmYul.Yul.Ast.Stmt) - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (final : EvmYul.Yul.State) - (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx - storage observableSlots switchId store) = .ok final) - (hStmtPreserves : - ∀ stmt, stmt ∈ body → - Backends.nativeSwitchMatchedTempName switchId ∉ - Backends.nativeStmtWriteNames stmt → - NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1) stmt (some contract)) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) - (some contract) - (nativeSwitchStoreInitialState contract tx storage observableSlots store) = - .ok final := by - apply exec_lowerNativeSwitchBlock_selector_find_hit_preserved_store_fuel - fuel selector switchId tag cases defaultBody body contract tx storage - observableSlots store final hSelector hFind hSelectorRange hTagsRange hBody - intro pre suffix _hCases - exact NativeBlockPreservesWord_of_nativeSwitchFresh_find_hit_matched - switchId selector tag body defaultBody cases (EvmYul.UInt256.ofNat 1) - (some contract) hFresh hFind hStmtPreserves +/-- Native primitive execution of `sstore(slot, 0)` on a word-canonical + initial runtime slot, lifted through Verity's projected native result + boundary with the EVMYulLean zero-write erasure lookup isolated. -/-- Store-parametric guarded selector-miss execution for the lowered switch - block whose default is `revert(0, 0)`. Lifts the empty-store version to - states already carrying additional bindings (e.g. `__has_selector := 1`). -/ -theorem exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_fuel - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) +This is the zero-write companion to +`primCall_sstore_initialState_wordSlot_projectResult_slot`: it proves the +actual native `SSTORE` primitive path and leaves only the map-level fact that +erasing a key makes the projected lookup miss. -/ +theorem primCall_sstore_initialState_wordSlot_projectResult_slot_zero_of_erase + (fuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = none) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases - [nativeRevertZeroZeroStmt]) - (some contract) - (.Ok (initialState contract tx storage observableSlots).sharedState store) = - .error EvmYul.Yul.Exception.Revert := by - let discrName := Backends.nativeSwitchDiscrTempName switchId - let matchedName := Backends.nativeSwitchMatchedTempName switchId - have hne := nativeSwitchDiscrTempName_ne_matchedTempName switchId - have hCases := - exec_nativeSwitchCaseIfs_find_none_with_revert_default_fuel - (fuel + 1) selector cases (some contract) _ discrName matchedName hFind - (nativeSwitchPrefixStoreState_matched_eq contract tx storage observableSlots - store discrName matchedName _) - (nativeSwitchPrefixStoreState_discr_eq contract tx storage observableSlots - store discrName matchedName selector hne hSelector) - hSelectorRange hTagsRange - exact exec_lowerNativeSwitchBlock_storePrefix_tail_error_fuel - (fuel + cases.length) switchId cases [nativeRevertZeroZeroStmt] - contract tx storage observableSlots store EvmYul.Yul.Exception.Revert - (by simpa [nativeSwitchTailStmts, discrName, matchedName, - Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hCases) + (slot value : Nat) + (hSlotRange : slot < EvmYul.UInt256.size) + (hValueZero : + (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = true) : + ∃ finalState, + EvmYul.Yul.primCall (fuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = + .ok (finalState, []) ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = + 0 := by + refine ⟨(initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (natToUInt256 slot) (natToUInt256 value)), ?_, ?_⟩ + · exact primCall_sstore_initialState_wordSlot_ok fuel contract tx storage + observableSlots slot value hSlotRange + · simp only [projectResult, projectStorageFromState, extractStorage, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, YulState.initial, toSharedState, + natToUInt256] + have hBranch : + (EvmYul.UInt256.ofNat value == (Inhabited.default : EvmYul.UInt256)) = + true := by + simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueZero + rw [hBranch] + have hErase : + (Batteries.RBMap.erase (projectStorage storage observableSlots) + (natToUInt256 slot)).find? (natToUInt256 slot) = none := + Batteries.RBMap.find?_erase_self _ _ + simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ + Std.ReflCmp.compare_self, IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hErase] -/-- Store-parametric guarded selector-hit execution for the lowered switch - block. Hit-case dual of `_find_none_with_revert_default_store_fuel`. -/ -theorem exec_lowerNativeSwitchBlock_selector_find_hit_error_store_fuel - (fuel selector switchId tag : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody body : List EvmYul.Yul.Ast.Stmt) - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) - (err : EvmYul.Yul.Exception) - (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) - ((((.Ok (initialState contract tx storage observableSlots).sharedState - store : EvmYul.Yul.State).insert - (Backends.nativeSwitchDiscrTempName switchId) - (EvmYul.UInt256.ofNat - (tx.functionSelector % Compiler.Constants.selectorModulus))).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 0)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1)) = .error err) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) - (some contract) - (.Ok (initialState contract tx storage observableSlots).sharedState store) = - .error err := by - let discrName := Backends.nativeSwitchDiscrTempName switchId - let matchedName := Backends.nativeSwitchMatchedTempName switchId - have hne := nativeSwitchDiscrTempName_ne_matchedTempName switchId - have hCases := - exec_nativeSwitchCaseIfs_find_hit_with_default_error_fuel - (fuel + 1) selector cases defaultBody tag body (some contract) _ - discrName matchedName err hFind - (nativeSwitchPrefixStoreState_matched_eq contract tx storage - observableSlots store discrName matchedName _) - (nativeSwitchPrefixStoreState_discr_eq contract tx storage - observableSlots store discrName matchedName selector hne hSelector) - hSelectorRange hTagsRange hBody - exact exec_lowerNativeSwitchBlock_storePrefix_tail_error_fuel - (fuel + cases.length) switchId cases defaultBody contract tx storage - observableSlots store err - (by simpa [nativeSwitchTailStmts, discrName, matchedName, - Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hCases) +/-- Native primitive execution of `sstore(slot, 0)` on a word-canonical + initial runtime slot with no observable slots materialized. The zero-write + erasure lookup is discharged by computation at the generic `SSTORE` + projection boundary. -/ +theorem primCall_sstore_initialState_wordSlot_projectResult_slot_zero_emptyObservable + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (slot value : Nat) + (hSlotRange : slot < EvmYul.UInt256.size) + (hValueZero : + (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = true) : + ∃ finalState, + EvmYul.Yul.primCall (fuel + 1) + (initialState contract tx storage []) + EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = + .ok (finalState, []) ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = + 0 := by + exact + primCall_sstore_initialState_wordSlot_projectResult_slot_zero_of_erase + fuel contract tx storage initialEvents [] slot value hSlotRange hValueZero + +/-- Native primitive execution of `sstore(slot, value)` from an initial runtime + shared state and arbitrary local-variable store, lifted through Verity's + projected native result boundary for a nonzero word-canonical write. This is + the generic dispatcher-local-store companion to + `primCall_sstore_initialState_wordSlot_projectResult_slot`. -/ +theorem primCall_sstore_initialState_wordSlot_withStore_projectResult_slot + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (slot value : Nat) + (hSlotRange : slot < EvmYul.UInt256.size) + (hValueNonzero : + (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = false) : + ∃ finalState, + EvmYul.Yul.primCall (fuel + 1) + (.Ok (initialState contract tx storage observableSlots).sharedState store) + EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = + .ok (finalState, []) ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = + natToUInt256 value := by + let initialWithStore : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + refine ⟨initialWithStore.setState + (initialWithStore.toState.sstore (natToUInt256 slot) (natToUInt256 value)), + ?_, ?_⟩ + · exact primCall_sstore_initialState_wordSlot_ok_withStore fuel contract tx + storage observableSlots store slot value hSlotRange + · dsimp [initialWithStore] + simp only [projectResult, projectStorageFromState, extractStorage, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, YulState.initial, toSharedState] + have hBranch : + (EvmYul.UInt256.ofNat value == (Inhabited.default : EvmYul.UInt256)) = + false := by + simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueNonzero + rw [hBranch] + simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ + Std.ReflCmp.compare_self] -/-- Bridge-shape selector-miss endpoint on the post-`__has_selector := 1` - state, yielding `.error Revert`. -/ -theorem exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) +/-- Native primitive execution of `sstore(slot, 0)` from an initial runtime + shared state and arbitrary local-variable store, lifted through Verity's + projected native result boundary with the zero-write erasure lookup + isolated. -/ +theorem primCall_sstore_initialState_wordSlot_withStore_projectResult_slot_zero_of_erase + (fuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = none) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : - EvmYul.Yul.exec (fuel + cases.length + 13) - (.Block [Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases - [nativeRevertZeroZeroStmt]]) - (some contract) - ((nativeSwitchInitialOkState contract tx storage observableSlots).insert - "__has_selector" (EvmYul.UInt256.ofNat 1)) = - .error EvmYul.Yul.Exception.Revert := by - have hEndpoint := - exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_fuel - fuel selector switchId cases contract tx storage observableSlots - ((∅ : EvmYul.Yul.VarStore).insert "__has_selector" (EvmYul.UInt256.ofNat 1)) - hSelector hFind hSelectorRange hTagsRange - have hStateEq : - (nativeSwitchInitialOkState contract tx storage observableSlots).insert - "__has_selector" (EvmYul.UInt256.ofNat 1) = - .Ok (initialState contract tx storage observableSlots).sharedState - ((∅ : EvmYul.Yul.VarStore).insert "__has_selector" - (EvmYul.UInt256.ofNat 1)) := by - simp [nativeSwitchInitialOkState, EvmYul.Yul.State.insert] - rw [hStateEq] - have hFuelEq : fuel + cases.length + 13 = (fuel + cases.length + 12).succ := by - omega - rw [hFuelEq] - exact exec_block_cons_error (fuel + cases.length + 12) _ [] _ _ - EvmYul.Yul.Exception.Revert hEndpoint - -/-- Bridge-shape selector-hit endpoint on the post-`__has_selector := 1` - state, yielding `.error err`. Hit-case dual of - `exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error`. -/ -theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error - (fuel selector switchId tag : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody body : List EvmYul.Yul.Ast.Stmt) - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (err : EvmYul.Yul.Exception) - (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx - storage observableSlots switchId nativeSwitchHasSelectorStore) = - .error err) : - EvmYul.Yul.exec (fuel + cases.length + 13) - (.Block [Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody]) - (some contract) - ((nativeSwitchInitialOkState contract tx storage observableSlots).insert - "__has_selector" (EvmYul.UInt256.ofNat 1)) = - .error err := by - have hEndpoint := exec_lowerNativeSwitchBlock_selector_find_hit_error_store_fuel - fuel selector switchId tag cases defaultBody body contract tx storage - observableSlots nativeSwitchHasSelectorStore err hSelector hFind - hSelectorRange hTagsRange (by - intro pre suffix hCases - simpa [nativeSwitchStoreMarkedPrefixStateForId, - nativeSwitchStorePrefixStateForId, nativeSwitchStoreInitialState, - nativeSwitchHasSelectorStore] using hBody pre suffix hCases) - have hFuelEq : fuel + cases.length + 13 = (fuel + cases.length + 12).succ := by omega - rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] - exact exec_block_cons_error (fuel + cases.length + 12) _ [] _ _ err hEndpoint + (store : EvmYul.Yul.VarStore) + (slot value : Nat) + (hSlotRange : slot < EvmYul.UInt256.size) + (hValueZero : + (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = true) : + ∃ finalState, + EvmYul.Yul.primCall (fuel + 1) + (.Ok (initialState contract tx storage observableSlots).sharedState store) + EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = + .ok (finalState, []) ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = + 0 := by + let initialWithStore : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + refine ⟨initialWithStore.setState + (initialWithStore.toState.sstore (natToUInt256 slot) (natToUInt256 value)), + ?_, ?_⟩ + · exact primCall_sstore_initialState_wordSlot_ok_withStore fuel contract tx + storage observableSlots store slot value hSlotRange + · dsimp [initialWithStore] + simp only [projectResult, projectStorageFromState, extractStorage, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, YulState.initial, toSharedState, + natToUInt256] + have hBranch : + (EvmYul.UInt256.ofNat value == (Inhabited.default : EvmYul.UInt256)) = + true := by + simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueZero + rw [hBranch] + have hErase : + (Batteries.RBMap.erase (projectStorage storage observableSlots) + (natToUInt256 slot)).find? (natToUInt256 slot) = none := + Batteries.RBMap.find?_erase_self _ _ + simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ + Std.ReflCmp.compare_self, IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hErase] -/-- Bridge-shape selector-hit endpoint on the post-`__has_selector := 1` - state, yielding the selected body's successful final state. This is the - success dual of - `exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error` - and derives the default-skip preservation premise from generated native - switch freshness. -/ -theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_fresh - (fuel selector switchId tag : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (defaultBody body : List EvmYul.Yul.Ast.Stmt) - (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (final : EvmYul.Yul.State) - (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) - (hFresh : - Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) - (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) - (some contract) - (nativeSwitchStoreMarkedPrefixStateForId contract tx storage - observableSlots switchId nativeSwitchHasSelectorStore) = .ok final) - (hStmtPreserves : - ∀ stmt, stmt ∈ body → - Backends.nativeSwitchMatchedTempName switchId ∉ - Backends.nativeStmtWriteNames stmt → - NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1) stmt (some contract)) : - EvmYul.Yul.exec (fuel + cases.length + 13) - (.Block [Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody]) - (some contract) - ((nativeSwitchInitialOkState contract tx storage observableSlots).insert - "__has_selector" (EvmYul.UInt256.ofNat 1)) = - .ok final := by - have hEndpoint := - exec_lowerNativeSwitchBlock_selector_find_hit_fresh_store_fuel - fuel selector switchId tag cases defaultBody body contract tx storage - observableSlots nativeSwitchHasSelectorStore final hSelector hFind - hSelectorRange hTagsRange hFresh hBody hStmtPreserves - have hFuelEq : fuel + cases.length + 13 = (fuel + cases.length + 12).succ := by - omega - rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] - exact exec_block_cons_ok (fuel + cases.length + 12) _ [] _ _ final final - hEndpoint (by simp [EvmYul.Yul.exec]) +/-- Native primitive execution of `sstore(slot, 0)` from an arbitrary local + store when no observable storage (IRStorageSlot.ofNat slot)s were materialized. -/ +theorem primCall_sstore_initialState_wordSlot_withStore_projectResult_slot_zero_emptyObservable + (fuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (store : EvmYul.Yul.VarStore) + (slot value : Nat) + (hSlotRange : slot < EvmYul.UInt256.size) + (hValueZero : + (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = true) : + ∃ finalState, + EvmYul.Yul.primCall (fuel + 1) + (.Ok (initialState contract tx storage []).sharedState store) + EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = + .ok (finalState, []) ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = + 0 := by + exact + primCall_sstore_initialState_wordSlot_withStore_projectResult_slot_zero_of_erase + fuel contract tx storage initialEvents [] store slot value hSlotRange + hValueZero -theorem exec_lowerNativeSwitchBlock_selector_find_none_without_default_fuel - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) +/-- Native primitive execution of the generated `store(uint256)` core, lifted + through Verity's projected native result boundary for call success and + absence of a return word. Storage-slot agreement remains the next setter + projection obligation, but callers no longer need to inspect the raw + `calldataload(4); sstore(0, arg0)` result shape for these fields. -/ +theorem primCall_calldataload4_then_sstore0_initialState_arg0_projectResult_ok + (loadFuel storeFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (hSelector : - selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = none) - (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases []) - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .ok (nativeSwitchPrefixFinalState contract tx storage observableSlots - (Backends.nativeSwitchDiscrTempName switchId) - (Backends.nativeSwitchMatchedTempName switchId)) := by - rw [lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts] - apply exec_nativeSwitchPrefix_then_tail_fuel - exact exec_nativeSwitchTail_find_none_without_default_fuel fuel selector - switchId cases contract tx storage observableSlots hSelector hFind - hSelectorRange hTagsRange + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) : + ∃ finalState, + (do + let (state', values) ← + EvmYul.Yul.primCall (loadFuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] + match values with + | [value] => + EvmYul.Yul.primCall (storeFuel + 1) state' + EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .ok (finalState, []) ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).success = true ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).returnValue = + none := by + refine ⟨(initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)), ?_, ?_, ?_⟩ + · exact primCall_calldataload4_then_sstore0_initialState_arg0_ok + loadFuel storeFuel contract tx storage observableSlots arg rest hArgs + · rfl + · rfl -@[simp] theorem initialState_unbridgedEnvironmentDefaults +/-- The native primitive sequence used by the generated SimpleStorage setter + body after dispatcher selection. -/ +def primCall_calldataload4_then_sstore0_stop_initialState_arg0 + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) : - (initialState contract tx storage observableSlots).sharedState.executionEnv.header.baseFeePerGas = - 0 ∧ - (initialState contract tx storage observableSlots).sharedState.executionEnv.header.blobGasUsed = - (0 : UInt64) ∧ - (initialState contract tx storage observableSlots).sharedState.executionEnv.header.excessBlobGas = - (0 : UInt64) ∧ - (initialState contract tx storage observableSlots).sharedState.executionEnv.blobVersionedHashes = - [] ∧ - EvmYul.State.chainId - (initialState contract tx storage observableSlots).sharedState.toState = - EvmYul.UInt256.ofNat EvmYul.chainId := by - simp [initialState, EvmYul.Yul.State.sharedState, YulState.initial, toSharedState, - mkBlockHeader, EvmYul.State.chainId] - -/-- Project the account storage for the current contract back to Verity's - `IRStorageSlot → IRStorageWord` storage view. -/ -def projectStorageFromState (tx : YulTransaction) (state : EvmYul.Yul.State) : - IRStorageSlot → IRStorageWord := - extractStorage state.sharedState (natToAddress tx.thisAddress) - -/-- Projecting final native storage reads the current contract account storage - entry for the requested slot. -/ -@[simp] theorem projectStorageFromState_accountStorageSlot - (tx : YulTransaction) - (state : EvmYul.Yul.State) - (slot : Nat) - (account : EvmYul.Account .Yul) - (value : EvmYul.UInt256) - (hAccount : - state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = - some account) - (hSlot : account.storage.find? (natToUInt256 slot) = some value) : - projectStorageFromState tx state (IRStorageSlot.ofNat slot) = value := by - simp [projectStorageFromState, extractStorage, hAccount, hSlot] - -/-- Projecting final native storage defaults to zero when the current contract - account has no native storage entry for the requested slot. -/ -@[simp] theorem projectStorageFromState_missingAccountStorageSlot - (tx : YulTransaction) - (state : EvmYul.Yul.State) - (slot : Nat) - (account : EvmYul.Account .Yul) - (hAccount : - state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = - some account) - (hSlot : account.storage.find? (natToUInt256 slot) = none) : - projectStorageFromState tx state (IRStorageSlot.ofNat slot) = 0 := by - simp [projectStorageFromState, extractStorage, hAccount, hSlot] - -/-- Projecting final native storage defaults to zero when the current contract - account is absent from the native account map. -/ -@[simp] theorem projectStorageFromState_missingAccount - (tx : YulTransaction) - (state : EvmYul.Yul.State) - (slot : Nat) - (hAccount : - state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = - none) : - projectStorageFromState tx state (IRStorageSlot.ofNat slot) = 0 := by - simp [projectStorageFromState, extractStorage, hAccount] + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := do + let (state', values) ← + EvmYul.Yul.primCall (loadFuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] + match values with + | [value] => + (do + let (state'', values') ← + EvmYul.Yul.primCall (storeFuel + 1) state' + EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] + match values' with + | [] => + EvmYul.Yul.primCall (stopFuel + 1) state'' + EvmYul.Operation.STOP [] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) + | _ => .error EvmYul.Yul.Exception.InvalidArguments -/-- Native initial-state storage materialization agrees with Verity storage on - every explicit observable slot. Slots and values are interpreted in the - EVM word domain, so the result is modulo `UInt256.size`. -/ -theorem initialState_observableStorageSlot +/-- Store-parametric form of the native primitive sequence used by the + generated SimpleStorage setter body. The lowered dispatcher executes the + selected body after adding switch temporaries to the Yul `VarStore`, while + calldata and storage effects are carried entirely by the shared state. -/ +def primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (slot : Nat) - (hSlot : slot ∈ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - projectStorageFromState tx - (initialState contract tx storage observableSlots) (IRStorageSlot.ofNat slot) = - storage (IRStorageSlot.ofNat slot) := by - simp only [projectStorageFromState, extractStorage, initialState, - EvmYul.Yul.State.sharedState, YulState.initial, toSharedState] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - have h := storageLookup_projectStorage storage observableSlots slot hSlot hRange - unfold storageLookup at h - exact h + (store : EvmYul.Yul.VarStore) : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := do + let (state', values) ← + EvmYul.Yul.primCall (loadFuel + 1) + (.Ok (initialState contract tx storage observableSlots).sharedState store) + EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] + match values with + | [value] => + (do + let (state'', values') ← + EvmYul.Yul.primCall (storeFuel + 1) state' + EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] + match values' with + | [] => + EvmYul.Yul.primCall (stopFuel + 1) state'' + EvmYul.Operation.STOP [] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) + | _ => .error EvmYul.Yul.Exception.InvalidArguments -/-- Native `sload` from an initially materialized observable slot returns the - exact EVM word projected from Verity storage. The range hypothesis keeps - the slot key word-canonical, so the finite native storage map cannot alias - another observed slot. -/ -theorem initialState_sload_observableSlot_value +/-- Exact native primitive execution shape for the generated SimpleStorage setter + body after dispatcher selection. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_eq + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (observableSlots : List Nat) - (slot : Nat) - (hSlot : slot ∈ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - (EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 slot)).2 = - storage (IRStorageSlot.ofNat slot) := by - have hFindStorage : - (projectStorage storage observableSlots).find? (natToUInt256 slot) = - some (storage (IRStorageSlot.ofNat slot)) := by - simpa [projectStorage, IRStorageWord.toUInt256] using - foldl_insert_find storage observableSlots slot hSlot hRange - (Batteries.RBMap.empty : EvmYul.Storage) - simp only [EvmYul.State.sload, EvmYul.State.lookupAccount, - EvmYul.Yul.State.toState, initialState, toSharedState, YulState.initial] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - change (Batteries.RBMap.find? (projectStorage storage observableSlots) - (natToUInt256 slot)).getD ⟨0⟩ = storage (IRStorageSlot.ofNat slot) - rw [hFindStorage] - rfl + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) : + let finalState := + (initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) + primCall_calldataload4_then_sstore0_stop_initialState_arg0 + loadFuel storeFuel stopFuel contract tx storage observableSlots = + .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by + dsimp + unfold primCall_calldataload4_then_sstore0_stop_initialState_arg0 + rw [primCall_calldataload4_initialState_arg0_ok loadFuel contract tx + storage observableSlots arg rest hArgs] + change + (do + let (state'', values') ← + EvmYul.Yul.primCall (storeFuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.SSTORE + [EvmYul.UInt256.ofNat 0, natToUInt256 arg] + match values' with + | [] => + EvmYul.Yul.primCall (stopFuel + 1) state'' + EvmYul.Operation.STOP [] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .error (EvmYul.Yul.Exception.YulHalt + ((initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg))) ⟨0⟩) + rw [primCall_sstore_initialState_wordSlot_ok storeFuel contract tx storage + observableSlots 0 arg (by norm_num [EvmYul.UInt256.size])] + exact primCall_stop_ok stopFuel _ -/-- Native `sload` from an initially materialized slot returns the exact bounded - IR storage word. This is the range-free version used after IR storage keys - moved to `IRStorageSlot`: Nat aliases modulo 2^256 carry the same bounded - key and therefore the same projected value. -/ -theorem initialState_sload_materializedSlot_value +/-- Exact native primitive execution shape for the generated SimpleStorage + setter body when the selected body starts with an arbitrary Yul + local-variable store. This removes the empty-store side condition left + around the dispatcher-selected setter path. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_eq + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (slots : List Nat) - (slot : Nat) - (hSlot : slot ∈ slots) : - (EvmYul.State.sload - (initialState contract tx storage slots).toState - (natToUInt256 slot)).2 = - storage (IRStorageSlot.ofNat slot) := by - have hFindStorage : - (projectStorage storage slots).find? (natToUInt256 slot) = - some (storage (IRStorageSlot.ofNat slot)) := by - simpa [projectStorage, IRStorageWord.toUInt256] using - foldl_insert_find_projected storage slots slot hSlot - (Batteries.RBMap.empty : EvmYul.Storage) - simp only [EvmYul.State.sload, EvmYul.State.lookupAccount, - EvmYul.Yul.State.toState, initialState, toSharedState, YulState.initial] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - change (Batteries.RBMap.find? (projectStorage storage slots) - (natToUInt256 slot)).getD ⟨0⟩ = storage (IRStorageSlot.ofNat slot) - rw [hFindStorage] - rfl + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) : + let initialWithStore : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + let finalState := + initialWithStore.setState + (initialWithStore.toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) + primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore + loadFuel storeFuel stopFuel contract tx storage observableSlots store = + .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by + dsimp + unfold primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore + rw [primCall_calldataload4_initialState_arg0_ok_withStore loadFuel contract + tx storage observableSlots store arg rest hArgs] + change + (do + let (state'', values') ← + EvmYul.Yul.primCall (storeFuel + 1) + (.Ok (initialState contract tx storage observableSlots).sharedState store) + EvmYul.Operation.SSTORE + [EvmYul.UInt256.ofNat 0, natToUInt256 arg] + match values' with + | [] => + EvmYul.Yul.primCall (stopFuel + 1) state'' + EvmYul.Operation.STOP [] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .error (EvmYul.Yul.Exception.YulHalt + ((.Ok (initialState contract tx storage observableSlots).sharedState store : + EvmYul.Yul.State).setState + ((.Ok (initialState contract tx storage observableSlots).sharedState store : + EvmYul.Yul.State).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg))) ⟨0⟩) + rw [primCall_sstore_initialState_wordSlot_ok_withStore storeFuel contract tx + storage observableSlots store 0 arg (by norm_num [EvmYul.UInt256.size])] + exact primCall_stop_ok stopFuel _ -/-- Projected storage is unchanged by the generated retrieve core - `sload(0); mstore(0, _); return(0, 32)`. The only `sload` state effect is - recording an accessed storage key, and `mstore`/`return` update only the - machine-state fields used for returndata. -/ -theorem projectStorageFromState_retrieveHit_initialState_materialized +/-- Native primitive execution of the full generated `store(uint256)` selected + body from an arbitrary local store, lifted through the terminating `STOP` + halt and Verity's projected native result boundary for call success and + absence of a return word. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_ok + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (slots : List Nat) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) - (slot : Nat) - (hSlot : slot ∈ slots) : - let shared := (initialState contract tx storage slots).sharedState - let p := shared.sload (EvmYul.UInt256.ofNat 0) - let shared1 : EvmYul.SharedState .Yul := { shared with toState := p.1 } - let shared2 : EvmYul.SharedState .Yul := - { shared1 with - toMachineState := - shared1.toMachineState.mstore (EvmYul.UInt256.ofNat 0) p.2 } - let shared3 : EvmYul.SharedState .Yul := - { shared2 with - toMachineState := - shared2.toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32) } - projectStorageFromState tx (EvmYul.Yul.State.Ok shared3 store) - (IRStorageSlot.ofNat slot) = - storage (IRStorageSlot.ofNat slot) := by - intro shared p shared1 shared2 shared3 - have hAccountMap : - shared3.accountMap = - (initialState contract tx storage slots).sharedState.accountMap := by - simp [shared3, shared2, shared1, p, shared, EvmYul.State.sload, - EvmYul.State.addAccessedStorageKey, EvmYul.Substate.addAccessedStorageKey] - simp only [projectStorageFromState, extractStorage, - EvmYul.Yul.State.sharedState, hAccountMap, initialState, YulState.initial, - toSharedState] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - have h := storageLookup_projectStorage_projected storage slots slot hSlot - unfold storageLookup at h - exact h + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) : + ∃ haltState haltValue, + primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore + loadFuel storeFuel stopFuel contract tx storage observableSlots store = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).success = + true ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = + none := by + let initialWithStore : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + let finalState := + initialWithStore.setState + (initialWithStore.toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) + refine ⟨finalState, ⟨0⟩, ?_, ?_, ?_⟩ + · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_eq + loadFuel storeFuel stopFuel contract tx storage observableSlots store arg + rest hArgs + · rfl + · rfl -/-- Native `sload` from an initially omitted materialized slot returns the EVM - zero word. The range hypotheses rule out modular aliasing between the omitted - slot and any materialized storage key. -/ -theorem initialState_sload_omittedSlot_value +/-- Exact projected result for the generated `store(uint256)` selected body + from an arbitrary dispatcher local store. This packages the + `CALLDATALOAD; SSTORE; STOP` native primitive sequence as one full + `YulResult` equality, rather than only exposing success and return-value + field facts. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_eq + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (slot : Nat) - (hNotSlot : slot ∉ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) - (hSlotRange : slot < EvmYul.UInt256.size) : - (EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 slot)).2 = - natToUInt256 0 := by - have hFindStorage : - (projectStorage storage observableSlots).find? (natToUInt256 slot) = none := by - simpa [projectStorage] using - foldl_insert_find_not_mem storage observableSlots slot hNotSlot hRange - hSlotRange (Batteries.RBMap.empty : EvmYul.Storage) - simp only [EvmYul.State.sload, EvmYul.State.lookupAccount, - EvmYul.Yul.State.toState, initialState, toSharedState, YulState.initial] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - change (Batteries.RBMap.find? (projectStorage storage observableSlots) - (natToUInt256 slot)).getD ⟨0⟩ = natToUInt256 0 - rw [hFindStorage] - rfl + (store : EvmYul.Yul.VarStore) + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) : + ∃ haltState haltValue, + primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore + loadFuel storeFuel stopFuel contract tx storage observableSlots store = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = + { success := true + returnValue := none + finalStorage := projectStorageFromState tx haltState + finalMappings := + Compiler.Proofs.storageAsMappings (projectStorageFromState tx haltState) + events := initialEvents ++ projectLogsFromState haltState } := by + let initialWithStore : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + let finalState := + initialWithStore.setState + (initialWithStore.toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) + refine ⟨finalState, ⟨0⟩, ?_, ?_⟩ + · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_eq + loadFuel storeFuel stopFuel contract tx storage observableSlots store arg + rest hArgs + · simp [projectResult] -/-- Native primitive execution of `sload(slot)` on an initially materialized, - word-canonical observable slot returns exactly the projected storage word. -/ -theorem primCall_sload_initialState_observableSlot_ok - (fuel : Nat) +/-- Exact projected result for the generated `store(uint256)` selected body at + the IR transaction boundary used by the end-to-end native theorem. This is + the `YulTransaction.ofIR` specialization of the dispatcher-local + `CALLDATALOAD; SSTORE; STOP` native primitive sequence. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_ofIR_arg0_withStore_projectResult_eq + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) + (tx : Compiler.Proofs.IRGeneration.IRTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (slot : Nat) - (hSlot : slot ∈ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - EvmYul.Yul.primCall (fuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.SLOAD [natToUInt256 slot] = - match EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 slot) with - | (state', _) => - .ok ((initialState contract tx storage observableSlots).setSharedState - { (initialState contract tx storage observableSlots).toSharedState with - toState := state' }, - [storage (IRStorageSlot.ofNat slot)]) := by - rw [primCall_sload_ok] - generalize hload : - EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 slot) = loaded - cases loaded with - | mk state' value => - have hvalue := - initialState_sload_observableSlot_value contract tx storage - observableSlots slot hSlot hRange - rw [hload] at hvalue - simp only at hvalue - simp [hvalue] + (store : EvmYul.Yul.VarStore) + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) : + ∃ haltState haltValue, + primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore + loadFuel storeFuel stopFuel contract (YulTransaction.ofIR tx) storage + observableSlots store = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = + { success := true + returnValue := none + finalStorage := projectStorageFromState (YulTransaction.ofIR tx) haltState + finalMappings := + Compiler.Proofs.storageAsMappings + (projectStorageFromState (YulTransaction.ofIR tx) haltState) + events := initialEvents ++ projectLogsFromState haltState } := by + exact + primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_eq + loadFuel storeFuel stopFuel contract (YulTransaction.ofIR tx) storage + initialEvents observableSlots store arg rest (by simpa using hArgs) -/-- Native primitive execution of `sload(slot)` on an initially omitted, - word-canonical materialization slot returns the EVM zero word. -/ -theorem primCall_sload_initialState_omittedSlot_ok - (fuel : Nat) +/-- Native primitive execution of the full generated `store(uint256)` selected + body from an arbitrary local store, lifted through `STOP` and Verity's + projected native result boundary for a nonzero slot-zero write. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_slot0 + (loadFuel storeFuel stopFuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) + (hValueNonzero : + (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = false) : + ∃ haltState haltValue, + primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore + loadFuel storeFuel stopFuel contract tx storage observableSlots store = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = + natToUInt256 arg := by + let initialWithStore : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + let finalState := + initialWithStore.setState + (initialWithStore.toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) + refine ⟨finalState, ⟨0⟩, ?_, ?_⟩ + · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_eq + loadFuel storeFuel stopFuel contract tx storage observableSlots store arg + rest hArgs + · dsimp [finalState, initialWithStore] + simp only [projectResult, projectStorageFromState, extractStorage, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, YulState.initial, toSharedState] + have hBranch : + (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = + false := by + simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueNonzero + rw [hBranch] + simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ + Std.ReflCmp.compare_self] + +/-- Zero-write storage projection for the full generated `store(uint256)` + selected body from an arbitrary local store, through the terminating + `STOP`, with the remaining RBMap erasure fact isolated. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_slot0_zero_of_erase + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (slot : Nat) - (hNotSlot : slot ∉ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) - (hSlotRange : slot < EvmYul.UInt256.size) : - EvmYul.Yul.primCall (fuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.SLOAD [natToUInt256 slot] = - match EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 slot) with - | (state', _) => - .ok ((initialState contract tx storage observableSlots).setSharedState - { (initialState contract tx storage observableSlots).toSharedState with - toState := state' }, - [natToUInt256 0]) := by - rw [primCall_sload_ok] - generalize hload : - EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 slot) = loaded - cases loaded with - | mk state' value => - have hvalue := - initialState_sload_omittedSlot_value contract tx storage - observableSlots slot hNotSlot hRange hSlotRange - rw [hload] at hvalue - simp only at hvalue - simp [hvalue] + (store : EvmYul.Yul.VarStore) + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) + (hValueZero : + (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : + ∃ haltState haltValue, + primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore + loadFuel storeFuel stopFuel contract tx storage observableSlots store = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = + 0 := by + let initialWithStore : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + let finalState := + initialWithStore.setState + (initialWithStore.toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) + refine ⟨finalState, ⟨0⟩, ?_, ?_⟩ + · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_eq + loadFuel storeFuel stopFuel contract tx storage observableSlots store arg + rest hArgs + · dsimp [finalState, initialWithStore] + simp only [projectResult, projectStorageFromState, extractStorage, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, YulState.initial, toSharedState, + natToUInt256] + have hBranch : + (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = + true := by + simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueZero + rw [hBranch] + have hErase : + (Batteries.RBMap.erase (projectStorage storage observableSlots) + (EvmYul.UInt256.ofNat 0)).find? (EvmYul.UInt256.ofNat 0) = none := + Batteries.RBMap.find?_erase_self _ _ + simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ + Std.ReflCmp.compare_self, IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hErase] -/-- Native primitive execution of `sload(slot)` is independent of the current - Yul local-variable store when reading an initially materialized, - word-canonical observable slot. This is the selected-body shape left after - the lowered dispatcher inserts switch temporaries. -/ -theorem primCall_sload_initialState_observableSlot_ok_withStore - (fuel : Nat) +/-- Zero-write storage projection for the full generated `store(uint256)` + selected body from an arbitrary local store when no observable slots were + materialized. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_slot0_zero_emptyObservable + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) + (initialEvents : List (List Nat)) (store : EvmYul.Yul.VarStore) - (slot : Nat) - (hSlot : slot ∈ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - EvmYul.Yul.primCall (fuel + 1) - (.Ok (initialState contract tx storage observableSlots).sharedState store) - EvmYul.Operation.SLOAD [natToUInt256 slot] = - match EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 slot) with - | (state', _) => - .ok (((.Ok (initialState contract tx storage observableSlots).sharedState - store : EvmYul.Yul.State).setSharedState - { (.Ok (initialState contract tx storage observableSlots).sharedState - store : EvmYul.Yul.State).toSharedState with - toState := state' }), - [storage (IRStorageSlot.ofNat slot)]) := by - rw [primCall_sload_ok] - generalize hload : - EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 slot) = loaded - cases loaded with - | mk state' value => - have hloadShared : - (initialState contract tx storage observableSlots).sharedState.sload - (natToUInt256 slot) = (state', value) := by - simpa [EvmYul.Yul.State.toState] using hload - have hvalue := - initialState_sload_observableSlot_value contract tx storage - observableSlots slot hSlot hRange - rw [hload] at hvalue - simp only at hvalue - simp [hloadShared, hvalue, EvmYul.Yul.State.toState] + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) + (hValueZero : + (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : + ∃ haltState haltValue, + primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore + loadFuel storeFuel stopFuel contract tx storage [] store = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = + 0 := by + exact + primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_slot0_zero_of_erase + loadFuel storeFuel stopFuel contract tx storage initialEvents [] store arg + rest hArgs hValueZero -/-- Native primitive execution of `sload(slot)` is independent of the current - Yul local-variable store when reading an omitted word-canonical slot. -/ -theorem primCall_sload_initialState_omittedSlot_ok_withStore - (fuel : Nat) +/-- Native primitive execution of the full generated `store(uint256)` selected + body tail: `calldataload(4); sstore(0, arg0); stop`. The terminating + `STOP` travels through EVMYulLean's Yul-halt channel and projects as a + successful call with no return word. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_projectResult_ok + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (slot : Nat) - (hNotSlot : slot ∉ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) - (hSlotRange : slot < EvmYul.UInt256.size) : - EvmYul.Yul.primCall (fuel + 1) - (.Ok (initialState contract tx storage observableSlots).sharedState store) - EvmYul.Operation.SLOAD [natToUInt256 slot] = - match EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 slot) with - | (state', _) => - .ok (((.Ok (initialState contract tx storage observableSlots).sharedState - store : EvmYul.Yul.State).setSharedState - { (.Ok (initialState contract tx storage observableSlots).sharedState - store : EvmYul.Yul.State).toSharedState with - toState := state' }), - [natToUInt256 0]) := by - rw [primCall_sload_ok] - generalize hload : - EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 slot) = loaded - cases loaded with - | mk state' value => - have hloadShared : - (initialState contract tx storage observableSlots).sharedState.sload - (natToUInt256 slot) = (state', value) := by - simpa [EvmYul.Yul.State.toState] using hload - have hvalue := - initialState_sload_omittedSlot_value contract tx storage - observableSlots slot hNotSlot hRange hSlotRange - rw [hload] at hvalue - simp only at hvalue - simp [hloadShared, hvalue, EvmYul.Yul.State.toState] + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) : + ∃ haltState haltValue, + primCall_calldataload4_then_sstore0_stop_initialState_arg0 + loadFuel storeFuel stopFuel contract tx storage observableSlots = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).success = + true ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = + none := by + let finalState := + (initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) + refine ⟨finalState, ⟨0⟩, ?_, ?_, ?_⟩ + · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_eq + loadFuel storeFuel stopFuel contract tx storage observableSlots arg rest + hArgs + · rfl + · rfl -/-- Native primitive execution of `sstore(slot, value)` on an initial runtime - state succeeds with the exact EVMYulLean `State.sstore` successor. The - range hypothesis records the word-canonical slot condition needed by the - dispatcher proof when this lemma is connected to projected storage. -/ -theorem primCall_sstore_initialState_wordSlot_ok - (fuel : Nat) +/-- Native primitive execution of the full generated `store(uint256)` selected + body, lifted through the terminating `STOP` halt and Verity's projected + native result boundary for a nonzero slot-zero write. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_projectResult_slot0 + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) + (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (slot value : Nat) - (_hSlotRange : slot < EvmYul.UInt256.size) : - EvmYul.Yul.primCall (fuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = - .ok (((initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (natToUInt256 slot) (natToUInt256 value))), []) := by - rw [primCall_sstore_ok] - simp [initialState, EvmYul.Yul.State.executionEnv] + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) + (hValueNonzero : + (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = false) : + ∃ haltState haltValue, + primCall_calldataload4_then_sstore0_stop_initialState_arg0 + loadFuel storeFuel stopFuel contract tx storage observableSlots = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = + natToUInt256 arg := by + let finalState := + (initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) + refine ⟨finalState, ⟨0⟩, ?_, ?_⟩ + · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_eq + loadFuel storeFuel stopFuel contract tx storage observableSlots arg rest + hArgs + · dsimp [finalState] + simp only [projectResult, projectStorageFromState, extractStorage, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, YulState.initial, toSharedState] + have hBranch : + (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = + false := by + simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueNonzero + rw [hBranch] + simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ + Std.ReflCmp.compare_self] -/-- Native primitive execution of `sstore(slot, value)` from an initial runtime - shared state is independent of the current Yul local-variable store. This - packages the word-slot storage write in the shape produced after dispatcher - switch temporaries have been inserted. -/ -theorem primCall_sstore_initialState_wordSlot_ok_withStore - (fuel : Nat) +/-- Zero-write storage projection for the full generated `store(uint256)` selected + body through the terminating `STOP`, with the remaining RBMap erasure fact + isolated at the same boundary as the non-terminating setter-core lemma. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_projectResult_slot0_zero_of_erase + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (slot value : Nat) - (_hSlotRange : slot < EvmYul.UInt256.size) : - EvmYul.Yul.primCall (fuel + 1) - (.Ok (initialState contract tx storage observableSlots).sharedState store) - EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = - .ok (((.Ok (initialState contract tx storage observableSlots).sharedState store : - EvmYul.Yul.State).setState - ((.Ok (initialState contract tx storage observableSlots).sharedState store : - EvmYul.Yul.State).toState.sstore - (natToUInt256 slot) (natToUInt256 value))), []) := by - rw [primCall_sstore_ok] - simp [initialState, EvmYul.Yul.State.sharedState, - EvmYul.Yul.State.executionEnv, YulState.initial, toSharedState] + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) + (hValueZero : + (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : + ∃ haltState haltValue, + primCall_calldataload4_then_sstore0_stop_initialState_arg0 + loadFuel storeFuel stopFuel contract tx storage observableSlots = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = + 0 := by + let finalState := + (initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) + refine ⟨finalState, ⟨0⟩, ?_, ?_⟩ + · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_eq + loadFuel storeFuel stopFuel contract tx storage observableSlots arg rest + hArgs + · dsimp [finalState] + simp only [projectResult, projectStorageFromState, extractStorage, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, YulState.initial, toSharedState, + natToUInt256] + have hBranch : + (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = + true := by + simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueZero + rw [hBranch] + have hErase : + (Batteries.RBMap.erase (projectStorage storage observableSlots) + (EvmYul.UInt256.ofNat 0)).find? (EvmYul.UInt256.ofNat 0) = none := + Batteries.RBMap.find?_erase_self _ _ + simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ + Std.ReflCmp.compare_self, IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hErase] -/-- Native primitive execution of the generated `store(uint256)` core: - `calldataload(4)` decodes the first ABI argument and the following - `sstore(0, value)` writes that word to slot zero. This is the real native - primitive sequence under the emitted SimpleStorage setter body, before the - terminating `stop`. -/ -theorem primCall_calldataload4_then_sstore0_initialState_arg0_ok - (loadFuel storeFuel : Nat) +/-- Zero-write storage projection for the full generated `store(uint256)` selected + body through `STOP` when no observable slots were materialized. -/ +theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_projectResult_slot0_zero_emptyObservable + (loadFuel storeFuel stopFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) + (initialEvents : List (List Nat)) (arg : Nat) (rest : List Nat) - (hArgs : tx.args = arg :: rest) : - (do - let (state', values) ← - EvmYul.Yul.primCall (loadFuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] - match values with - | [value] => - EvmYul.Yul.primCall (storeFuel + 1) state' - EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .ok (((initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg))), []) := by - rw [primCall_calldataload4_initialState_arg0_ok loadFuel contract tx storage - observableSlots arg rest hArgs] - change EvmYul.Yul.primCall (storeFuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, natToUInt256 arg] = - .ok (((initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg))), []) - exact primCall_sstore_initialState_wordSlot_ok storeFuel contract tx storage - observableSlots 0 arg (by norm_num [EvmYul.UInt256.size]) - -/-- Native primitive execution of the `return(0, 32)` half of the generated - scalar-return sequence after `mstore(0, value)`. EVMYulLean models `RETURN` - as a Yul halt carrying the post-`evmReturn` state; the halt literal is the - default nonzero marker produced by `binaryMachineStateOp`, while the actual - returned bytes live in the state's `H_return` buffer. -/ -theorem primCall_return32_after_mstore0_ok - (fuel : Nat) - (state : EvmYul.Yul.State) - (value : EvmYul.UInt256) : - EvmYul.Yul.primCall (fuel + 1) - (state.setMachineState - (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value)) - EvmYul.Operation.RETURN - [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] = - .error (EvmYul.Yul.Exception.YulHalt - ((state.setMachineState - (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value)).setMachineState - ((state.setMachineState - (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value)).toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32))) - ⟨1⟩) := by - rw [primCall_return_ok] - simp [EvmYul.Yul.binaryMachineStateOp] - -/-- Native primitive execution of the generated scalar-return instruction pair - through EVMYulLean's actual `MSTORE` and `RETURN` primitive relation. This - exposes the exact halt state that remains to be connected to Verity's - single-word `returnValue` projection. -/ -theorem primCall_mstore0_then_return32_ok - (mstoreFuel returnFuel : Nat) - (state : EvmYul.Yul.State) - (value : EvmYul.UInt256) : - (do - let (state', values) ← - EvmYul.Yul.primCall (mstoreFuel + 1) state - EvmYul.Operation.MSTORE - [EvmYul.UInt256.ofNat 0, value] - match values with - | [] => - EvmYul.Yul.primCall (returnFuel + 1) state' - EvmYul.Operation.RETURN - [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .error (EvmYul.Yul.Exception.YulHalt - ((state.setMachineState - (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value)).setMachineState - ((state.setMachineState - (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value)).toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32))) - ⟨1⟩) := by - rw [primCall_mstore_ok] - exact primCall_return32_after_mstore0_ok returnFuel state value - -/-- The native return buffer produced by `mstore(0, value); return(0, 32)` is - exactly one EVM word wide. -/ -theorem mstore0_then_return32_hReturn_size - (sharedState : EvmYul.SharedState .Yul) - (store : EvmYul.Yul.VarStore) - (value : EvmYul.UInt256) : - let state : EvmYul.Yul.State := .Ok sharedState store - let stored := - state.setMachineState - (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value) - let returned := - stored.setMachineState - (stored.toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32)) - returned.sharedState.H_return.size = 32 := by - dsimp - have hZero : (EvmYul.UInt256.ofNat 0).toNat = 0 := by - rfl - have hLen : (EvmYul.UInt256.ofNat 32).toNat = 32 := by - rfl - simp [EvmYul.MachineState.evmReturn, readWithPadding_32_size, - EvmYul.MachineState.mstore, - EvmYul.MachineState.writeWord, EvmYul.writeBytes, - EvmYul.UInt256.toByteArray, EvmYul.Yul.State.setMachineState, - EvmYul.Yul.State.sharedState, EvmYul.Yul.State.toMachineState, hZero, hLen] - -/-- If the generated scalar-return sequence starts from empty memory and the - value word is represented by exactly 32 bytes, then the native `RETURN` - halt buffer is byte-for-byte the word written by `MSTORE`. -/ -theorem mstore0_then_return32_emptyMemory_hReturn_eq - (sharedState : EvmYul.SharedState .Yul) - (store : EvmYul.Yul.VarStore) - (value : EvmYul.UInt256) - (hMemory : sharedState.memory = ByteArray.empty) - (hValueSize : value.toByteArray.size = 32) : - let state : EvmYul.Yul.State := .Ok sharedState store - let stored := - state.setMachineState - (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value) - let returned := - stored.setMachineState - (stored.toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32)) - returned.sharedState.H_return = value.toByteArray := by - dsimp - simp only [EvmYul.Yul.State.toMachineState, EvmYul.Yul.State.setMachineState, - EvmYul.Yul.State.sharedState] - simp only [EvmYul.MachineState.mstore, EvmYul.MachineState.writeWord, - EvmYul.writeBytes, EvmYul.MachineState.evmReturn] - simp only [hMemory] - exact byteArray_write_empty_zero_32_readWithPadding_eq_of_size - value.toByteArray hValueSize - -/-- The generated scalar-return sequence started from empty memory returns - exactly the 32-byte representation of the word written at offset zero. -/ -theorem mstore0_then_return32_emptyMemory_hReturn_eq_toByteArray - (sharedState : EvmYul.SharedState .Yul) - (store : EvmYul.Yul.VarStore) - (value : EvmYul.UInt256) - (hMemory : sharedState.memory = ByteArray.empty) : - let state : EvmYul.Yul.State := .Ok sharedState store - let stored := - state.setMachineState - (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value) - let returned := - stored.setMachineState - (stored.toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32)) - returned.sharedState.H_return = value.toByteArray := - mstore0_then_return32_emptyMemory_hReturn_eq sharedState store value hMemory - (uint256_toByteArray_size value) - -/-- The concrete native primitive execution theorem for the generated scalar - return sequence carries a one-word return buffer when started from an - executable `Ok` Yul state. -/ -theorem primCall_mstore0_then_return32_ok_hReturn_size - (mstoreFuel returnFuel : Nat) - (sharedState : EvmYul.SharedState .Yul) - (store : EvmYul.Yul.VarStore) - (value : EvmYul.UInt256) : + (hArgs : tx.args = arg :: rest) + (hValueZero : + (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : ∃ haltState haltValue, + primCall_calldataload4_then_sstore0_stop_initialState_arg0 + loadFuel storeFuel stopFuel contract tx storage [] = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = + 0 := by + exact + primCall_calldataload4_then_sstore0_stop_initialState_arg0_projectResult_slot0_zero_of_erase + loadFuel storeFuel stopFuel contract tx storage initialEvents [] arg rest + hArgs hValueZero + +/-- Native primitive execution of the generated `store(uint256)` core, lifted + through Verity's projected native result boundary for a nonzero slot-zero + write. The remaining zero-write case goes through `Account.updateStorage`'s + key-erasure branch and needs the corresponding `RBMap.erase` lookup fact. -/ +theorem primCall_calldataload4_then_sstore0_initialState_arg0_projectResult_slot0 + (loadFuel storeFuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) + (hValueNonzero : + (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = false) : + ∃ finalState, (do let (state', values) ← - EvmYul.Yul.primCall (mstoreFuel + 1) (.Ok sharedState store) - EvmYul.Operation.MSTORE - [EvmYul.UInt256.ofNat 0, value] + EvmYul.Yul.primCall (loadFuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] match values with - | [] => - EvmYul.Yul.primCall (returnFuel + 1) state' - EvmYul.Operation.RETURN - [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] + | [value] => + EvmYul.Yul.primCall (storeFuel + 1) state' + EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - haltState.sharedState.H_return.size = 32 := by - refine ⟨ - ((EvmYul.Yul.State.Ok sharedState store).setMachineState - ((EvmYul.Yul.State.Ok sharedState store).toMachineState.mstore - (EvmYul.UInt256.ofNat 0) value)).setMachineState - (((EvmYul.Yul.State.Ok sharedState store).setMachineState - ((EvmYul.Yul.State.Ok sharedState store).toMachineState.mstore - (EvmYul.UInt256.ofNat 0) value)).toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32)), - ⟨1⟩, ?_⟩ - constructor - · exact primCall_mstore0_then_return32_ok mstoreFuel returnFuel - (.Ok sharedState store) value - · exact mstore0_then_return32_hReturn_size sharedState store value + .ok (finalState, []) ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat 0) = + natToUInt256 arg := by + refine ⟨(initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)), ?_, ?_⟩ + · exact primCall_calldataload4_then_sstore0_initialState_arg0_ok + loadFuel storeFuel contract tx storage observableSlots arg rest hArgs + · simp only [projectResult, projectStorageFromState, extractStorage, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, YulState.initial, toSharedState] + have hBranch : + (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = + false := by + simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueNonzero + rw [hBranch] + simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ + Std.ReflCmp.compare_self] -/-- Native initial-state storage materialization defaults omitted observable - pre-state slots to zero. The in-range hypotheses rule out modular aliasing - through the EVM word key used by the finite native storage map. -/ -theorem initialState_omittedStorageSlot +/-- Zero `sstore` projection, with the remaining RBMap erasure fact isolated. -/ +theorem primCall_calldataload4_then_sstore0_initialState_arg0_projectResult_slot0_zero_of_erase + (loadFuel storeFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (slot : Nat) - (hNotSlot : slot ∉ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) - (hSlotRange : slot < EvmYul.UInt256.size) : - projectStorageFromState tx - (initialState contract tx storage observableSlots) (IRStorageSlot.ofNat slot) = 0 := by - simp only [projectStorageFromState, extractStorage, initialState, - EvmYul.Yul.State.sharedState, YulState.initial, toSharedState] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - rw [Batteries.RBMap.find?_insert_of_eq _ Std.ReflCmp.compare_self] - simp only - have h := foldl_insert_find_not_mem storage observableSlots slot hNotSlot - hRange hSlotRange (Batteries.RBMap.empty : EvmYul.Storage) - have hNone : - (projectStorage storage observableSlots).find? (natToUInt256 slot) = none := by - simpa [projectStorage] using h - simp [IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hNone] - -/-- Decode one 32-byte big-endian word from an EVMYulLean byte array. -/ -def byteArrayWord (bytes : ByteArray) (offset : Nat) : Nat := - (List.range 32).foldl - (fun acc i => (acc * 256 + ((bytes.get? (offset + i)).getD 0).toNat) % - Compiler.Constants.evmModulus) - 0 - -private def listByteArrayWordNoMod (bytes : List UInt8) (n : Nat) : Nat := - (List.range n).foldl - (fun acc i => acc * 256 + ((bytes[i]?).getD 0).toNat) 0 - -private def listByteArrayWordMod (bytes : List UInt8) (n : Nat) : Nat := - (List.range n).foldl - (fun acc i => (acc * 256 + ((bytes[i]?).getD 0).toNat) % - Compiler.Constants.evmModulus) 0 - -private theorem fromBytes'_reverse_append_single (xs : List UInt8) (b : UInt8) : - EvmYul.fromBytes' ((xs ++ [b]).reverse) = - EvmYul.fromBytes' xs.reverse * 256 + b.toNat := by - simp [EvmYul.fromBytes'] - omega - -private theorem listByteArrayWordNoMod_eq_fromBytes'_take_reverse - (bytes : List UInt8) (n : Nat) - (hn : n ≤ bytes.length) : - listByteArrayWordNoMod bytes n = - EvmYul.fromBytes' (bytes.take n).reverse := by - induction n with - | zero => - simp [listByteArrayWordNoMod, EvmYul.fromBytes'] - | succ n ih => - have hn' : n ≤ bytes.length := by omega - have hlt : n < bytes.length := by omega - unfold listByteArrayWordNoMod at ih ⊢ - rw [List.range_succ, List.foldl_append] - simp only [List.foldl_cons, List.foldl_nil] - rw [ih hn'] - rw [List.take_succ] - rw [List.getElem?_eq_getElem hlt] - simp only [Option.getD_some, Option.toList_some] - rw [fromBytes'_reverse_append_single] - -private theorem listByteArrayWordNoMod_lt - (bytes : List UInt8) (n : Nat) - (hn : n ≤ bytes.length) : - listByteArrayWordNoMod bytes n < 2 ^ (8 * n) := by - rw [listByteArrayWordNoMod_eq_fromBytes'_take_reverse bytes n hn] - have h := fromBytes'_lt (bytes.take n).reverse - have hlen : (bytes.take n).reverse.length = n := by - simp [List.length_take, hn] - simpa [hlen] using h - -private theorem listByteArrayWordMod_eq_noMod - (bytes : List UInt8) (n : Nat) - (hnLen : n ≤ bytes.length) (hnWord : n ≤ 32) : - listByteArrayWordMod bytes n = listByteArrayWordNoMod bytes n := by - induction n with - | zero => - simp [listByteArrayWordMod, listByteArrayWordNoMod] - | succ n ih => - have hnLen' : n ≤ bytes.length := by omega - have hnWord' : n ≤ 32 := by omega - unfold listByteArrayWordMod listByteArrayWordNoMod at ih ⊢ - rw [List.range_succ, List.foldl_append, List.foldl_append] - simp only [List.foldl_cons, List.foldl_nil] - rw [ih hnLen' hnWord'] - have hNoMod : - (List.foldl (fun acc i => acc * 256 + (bytes[i]?.getD 0).toNat) 0 - (List.range n) * - 256 + - (bytes[n]?.getD 0).toNat) < Compiler.Constants.evmModulus := by - rw [show - List.foldl (fun acc i => acc * 256 + (bytes[i]?.getD 0).toNat) - 0 (List.range n) = - listByteArrayWordNoMod bytes n by rfl] - have hprev := listByteArrayWordNoMod_lt bytes n hnLen' - have hb : (bytes[n]?.getD 0).toNat < 256 := by - cases hopt : bytes[n]? - · simp - · simp - exact UInt8.toNat_lt _ - have hpow : 2 ^ (8 * n) * 256 = 2 ^ (8 * (n + 1)) := by - rw [Nat.mul_add, Nat.pow_add] - have hle : 2 ^ (8 * (n + 1)) ≤ Compiler.Constants.evmModulus := by - have : 8 * (n + 1) ≤ 256 := by omega - unfold Compiler.Constants.evmModulus - exact Nat.pow_le_pow_right (by norm_num) this - nlinarith - rw [Nat.mod_eq_of_lt hNoMod] - -private theorem byteArray_get?_data_toList (bytes : ByteArray) (i : Nat) : - bytes.get? i = bytes.data.toList[i]? := by - unfold ByteArray.get? - split - · rw [Array.getElem?_toList] - simp [ByteArray.get] - · rename_i h - have hlen : bytes.data.toList.length ≤ i := by - simp [ByteArray.size] at h - simpa using h - have hnone : bytes.data.toList[i]? = none := List.getElem?_eq_none hlen - exact hnone.symm - -theorem byteArrayWord_eq_fromBytes'_reverse_of_size - (bytes : ByteArray) - (hSize : bytes.size = 32) : - byteArrayWord bytes 0 = EvmYul.fromBytes' bytes.data.toList.reverse := by - have hLen : bytes.data.toList.length = 32 := by - simpa [ByteArray.size] using hSize - unfold byteArrayWord - rw [show - List.foldl - (fun acc i => (acc * 256 + ((bytes.get? (0 + i)).getD 0).toNat) % - Compiler.Constants.evmModulus) - 0 (List.range 32) = - listByteArrayWordMod bytes.data.toList 32 by - simp [listByteArrayWordMod, byteArray_get?_data_toList]] - rw [listByteArrayWordMod_eq_noMod bytes.data.toList 32 (by omega) (by omega)] - have hNoMod := - listByteArrayWordNoMod_eq_fromBytes'_take_reverse bytes.data.toList 32 - (by omega) - rw [hNoMod] - rw [show bytes.data.toList.take 32 = bytes.data.toList by - rw [← hLen, List.take_length]] - -private theorem fromBytes'_replicate_zero (n : Nat) : - EvmYul.fromBytes' (List.replicate n (0 : UInt8)) = 0 := by - induction n with - | zero => - simp [EvmYul.fromBytes'] - | succ n ih => - simp [List.replicate, EvmYul.fromBytes', ih] - -private theorem fromBytes'_append_replicate_zero (xs : List UInt8) (n : Nat) : - EvmYul.fromBytes' (xs ++ List.replicate n (0 : UInt8)) = - EvmYul.fromBytes' xs := by - rw [fromBytes'_append] - simp [fromBytes'_replicate_zero] - -theorem byteArrayWord_uint256_toByteArray - (value : EvmYul.UInt256) : - byteArrayWord value.toByteArray 0 = value.toNat := by - rw [byteArrayWord_eq_fromBytes'_reverse_of_size - value.toByteArray (uint256_toByteArray_size value)] - unfold EvmYul.UInt256.toByteArray BE - simp [ByteArray.data_append, ffi.ByteArray.zeroes, - list_toByteArray_data_toList] - simp [EvmYul.toBytesBigEndian] - -/-- Decode the word-granular payload used by Verity's proof-side log model. -/ -def byteArrayLogWords (bytes : ByteArray) : List Nat := - (List.range (bytes.size / 32)).map (fun i => byteArrayWord bytes (i * 32)) - -/-- Project native EVMYulLean logs to the current Verity observable event shape: - topics followed by word-aligned log data. -/ -def projectLogEntry (entry : EvmYul.LogEntry) : List Nat := - entry.topics.toList.map uint256ToNat ++ byteArrayLogWords entry.data + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) + (hValueZero : + (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : + ∃ finalState, + (do + let (state', values) ← + EvmYul.Yul.primCall (loadFuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] + match values with + | [value] => + EvmYul.Yul.primCall (storeFuel + 1) state' + EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .ok (finalState, []) ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat 0) = + 0 := by + refine ⟨(initialState contract tx storage observableSlots).setState + ((initialState contract tx storage observableSlots).toState.sstore + (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)), ?_, ?_⟩ + · exact primCall_calldataload4_then_sstore0_initialState_arg0_ok + loadFuel storeFuel contract tx storage observableSlots arg rest hArgs + · simp only [projectResult, projectStorageFromState, extractStorage, + initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, + EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, + EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, + EvmYul.Account.updateStorage, YulState.initial, toSharedState, + natToUInt256] + have hBranch : + (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = + true := by + simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueZero + rw [hBranch] + have hErase : + (Batteries.RBMap.erase (projectStorage storage observableSlots) + (EvmYul.UInt256.ofNat 0)).find? (EvmYul.UInt256.ofNat 0) = none := + Batteries.RBMap.find?_erase_self _ _ + simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ + Std.ReflCmp.compare_self, IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hErase] -def projectLogsFromState (state : EvmYul.Yul.State) : List (List Nat) := - state.sharedState.substate.logSeries.toList.map projectLogEntry +/-- Zero `sstore` projection with empty observable-slot materialization. -/ +theorem primCall_calldataload4_then_sstore0_initialState_arg0_projectResult_slot0_zero_emptyObservable + (loadFuel storeFuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (arg : Nat) + (rest : List Nat) + (hArgs : tx.args = arg :: rest) + (hValueZero : + (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : + ∃ finalState, + (do + let (state', values) ← + EvmYul.Yul.primCall (loadFuel + 1) + (initialState contract tx storage []) + EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] + match values with + | [value] => + EvmYul.Yul.primCall (storeFuel + 1) state' + EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .ok (finalState, []) ∧ + (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat 0) = + 0 := by + exact + primCall_calldataload4_then_sstore0_initialState_arg0_projectResult_slot0_zero_of_erase + loadFuel storeFuel contract tx storage initialEvents [] arg rest hArgs + hValueZero -@[simp] theorem projectLogEntry_topicsAndWordData - (entry : EvmYul.LogEntry) : - projectLogEntry entry = - entry.topics.toList.map uint256ToNat ++ byteArrayLogWords entry.data := by +@[simp] theorem projectResult_yulHalt_events + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (value : EvmYul.Yul.Ast.Literal) : + (projectResult tx initialStorage initialEvents + (.error (.YulHalt state value))).events = + initialEvents ++ projectLogsFromState state := by rfl -@[simp] theorem projectLogsFromState_logSeries - (state : EvmYul.Yul.State) : - projectLogsFromState state = - state.sharedState.substate.logSeries.toList.map projectLogEntry := by +@[simp] theorem projectResult_yulHalt_success + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (state : EvmYul.Yul.State) + (value : EvmYul.Yul.Ast.Literal) : + (projectResult tx initialStorage initialEvents + (.error (.YulHalt state value))).success = true := by rfl -/-- Project a native Yul halt produced by `return`/`stop` to Verity's single-word - return observable. EVMYulLean represents `stop` as `YulHalt _ 0`; `return` - goes through `H_return`, matching the proof oracle's 32-byte return case. -/ -def projectHaltReturn (state : EvmYul.Yul.State) (haltValue : EvmYul.Yul.Ast.Literal) : - Option Nat := - if haltValue = ⟨0⟩ then - none - else if state.sharedState.H_return.size = 32 then - some (byteArrayWord state.sharedState.H_return 0) - else - some 0 - -@[simp] theorem projectHaltReturn_stop - (state : EvmYul.Yul.State) : - projectHaltReturn state ⟨0⟩ = none := by - simp [projectHaltReturn] - -@[simp] theorem projectHaltReturn_32ByteReturn +@[simp] theorem projectResult_yulHalt_returnValue + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (state : EvmYul.Yul.State) - (haltValue : EvmYul.Yul.Ast.Literal) - (hHalt : haltValue ≠ ⟨0⟩) - (hSize : state.sharedState.H_return.size = 32) : - projectHaltReturn state haltValue = - some (byteArrayWord state.sharedState.H_return 0) := by - simp [projectHaltReturn, hHalt, hSize] + (value : EvmYul.Yul.Ast.Literal) : + (projectResult tx initialStorage initialEvents + (.error (.YulHalt state value))).returnValue = + projectHaltReturn state value := by + rfl -/-- Until wider returndata support lands, a non-`stop` halt with a native return - buffer whose size is not exactly one ABI word projects to the conservative - single-word fallback used by the current proof-side observable model. -/ -@[simp] theorem projectHaltReturn_non32ByteReturn - (state : EvmYul.Yul.State) - (haltValue : EvmYul.Yul.Ast.Literal) - (hHalt : haltValue ≠ ⟨0⟩) - (hSize : state.sharedState.H_return.size ≠ 32) : - projectHaltReturn state haltValue = some 0 := by - simp [projectHaltReturn, hHalt, hSize] +/-- The exact native scalar-return primitive proof lifted through Verity's + projected native result boundary. This is the shape consumed by dispatcher + agreement: after native `mstore(0, value); return(0, 32)` halts, the + projected `YulResult.returnValue` is exactly the returned word. -/ +theorem primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue + (mstoreFuel returnFuel : Nat) + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (sharedState : EvmYul.SharedState .Yul) + (store : EvmYul.Yul.VarStore) + (value : EvmYul.UInt256) + (hMemory : sharedState.memory = ByteArray.empty) : + ∃ haltState haltValue, + (do + let (state', values) ← + EvmYul.Yul.primCall (mstoreFuel + 1) (.Ok sharedState store) + EvmYul.Operation.MSTORE + [EvmYul.UInt256.ofNat 0, value] + match values with + | [] => + EvmYul.Yul.primCall (returnFuel + 1) state' + EvmYul.Operation.RETURN + [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx initialStorage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = + some value.toNat := by + rcases primCall_mstore0_then_return32_emptyMemory_projectHaltReturn + mstoreFuel returnFuel sharedState store value hMemory with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, hExec, ?_⟩ + simpa using hReturn -theorem primCall_mstore0_then_return32_emptyMemory_projectHaltReturn +/-- Exact projected result for the generated scalar-return primitive sequence. + Starting from empty native memory, `mstore(0, value); return(0, 32)` halts + through the actual EVMYulLean primitive relation and projects as a successful + one-word return containing exactly `value`. -/ +theorem primCall_mstore0_then_return32_emptyMemory_projectResult_eq (mstoreFuel returnFuel : Nat) + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (sharedState : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (value : EvmYul.UInt256) (hMemory : sharedState.memory = ByteArray.empty) : ∃ haltState haltValue, (do - let (state', values) ← - EvmYul.Yul.primCall (mstoreFuel + 1) (.Ok sharedState store) - EvmYul.Operation.MSTORE - [EvmYul.UInt256.ofNat 0, value] - match values with + let (state', values) ← + EvmYul.Yul.primCall (mstoreFuel + 1) (.Ok sharedState store) + EvmYul.Operation.MSTORE + [EvmYul.UInt256.ofNat 0, value] + match values with + | [] => + EvmYul.Yul.primCall (returnFuel + 1) state' + EvmYul.Operation.RETURN + [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + projectResult tx initialStorage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = + { success := true + returnValue := some value.toNat + finalStorage := projectStorageFromState tx haltState + finalMappings := + Compiler.Proofs.storageAsMappings (projectStorageFromState tx haltState) + events := initialEvents ++ projectLogsFromState haltState } := by + rcases + primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue + mstoreFuel returnFuel tx initialStorage initialEvents sharedState store value + hMemory with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, hExec, ?_⟩ + have hProjectReturn : + projectHaltReturn haltState haltValue = some value.toNat := by + simpa [projectResult] using hReturn + simp [projectResult, hProjectReturn] + +/-- The native primitive sequence used by the generated SimpleStorage getter + body after dispatcher selection. -/ +def primCall_sload0_then_mstore0_return32_initialState + (sloadFuel mstoreFuel returnFuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := do + let (state', values) ← + EvmYul.Yul.primCall (sloadFuel + 1) + (initialState contract tx storage observableSlots) + EvmYul.Operation.SLOAD [EvmYul.UInt256.ofNat 0] + match values with + | [value] => + (do + let (state'', values') ← + EvmYul.Yul.primCall (mstoreFuel + 1) state' + EvmYul.Operation.MSTORE [EvmYul.UInt256.ofNat 0, value] + match values' with + | [] => + EvmYul.Yul.primCall (returnFuel + 1) state'' + EvmYul.Operation.RETURN + [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] + | _ => .error EvmYul.Yul.Exception.InvalidArguments) + | _ => .error EvmYul.Yul.Exception.InvalidArguments + +/-- Store-parametric form of the native primitive sequence used by the + generated SimpleStorage getter body. The lowered dispatcher executes the + selected body after adding switch temporaries to the Yul `VarStore`, while + storage and memory effects are carried by the shared state. -/ +def primCall_sload0_then_mstore0_return32_initialState_withStore + (sloadFuel mstoreFuel returnFuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) : + Except EvmYul.Yul.Exception + (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := do + let (state', values) ← + EvmYul.Yul.primCall (sloadFuel + 1) + (.Ok (initialState contract tx storage observableSlots).sharedState store) + EvmYul.Operation.SLOAD [EvmYul.UInt256.ofNat 0] + match values with + | [value] => + (do + let (state'', values') ← + EvmYul.Yul.primCall (mstoreFuel + 1) state' + EvmYul.Operation.MSTORE [EvmYul.UInt256.ofNat 0, value] + match values' with | [] => - EvmYul.Yul.primCall (returnFuel + 1) state' + EvmYul.Yul.primCall (returnFuel + 1) state'' EvmYul.Operation.RETURN [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - projectHaltReturn haltState haltValue = some value.toNat := by - let state : EvmYul.Yul.State := .Ok sharedState store - let stored := - state.setMachineState - (state.toMachineState.mstore (EvmYul.UInt256.ofNat 0) value) - let returned := - stored.setMachineState - (stored.toMachineState.evmReturn - (EvmYul.UInt256.ofNat 0) (EvmYul.UInt256.ofNat 32)) - refine ⟨returned, ⟨1⟩, ?_⟩ - constructor - · exact primCall_mstore0_then_return32_ok mstoreFuel returnFuel - (.Ok sharedState store) value - · have hHalt : (⟨1⟩ : EvmYul.Yul.Ast.Literal) ≠ ⟨0⟩ := by - intro h - norm_num [EvmYul.UInt256.size] at h - have hSize : returned.sharedState.H_return.size = 32 := by - exact mstore0_then_return32_hReturn_size sharedState store value - have hReturn : returned.sharedState.H_return = value.toByteArray := by - exact mstore0_then_return32_emptyMemory_hReturn_eq_toByteArray - sharedState store value hMemory - rw [projectHaltReturn_32ByteReturn returned ⟨1⟩ hHalt hSize] - rw [hReturn, byteArrayWord_uint256_toByteArray] - -/-- The dispatcher-block execution that `EvmYul.Yul.callDispatcher` performs - after its initial fuel check and empty-argument call-frame setup. - -Keeping this expression named lets the native/interpreter bridge target -statement execution of the lowered dispatcher body directly, instead of -re-opening the full `callDispatcher` wrapper at each EndToEnd proof site. -/ -def callDispatcherBlockResult - (fuel' : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (initial : EvmYul.Yul.State) : - Except EvmYul.Yul.Exception - (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := - let dispatcherDef := - EvmYul.Yul.Ast.FunctionDefinition.Def [] [] - [initial.executionEnv.code.dispatcher] - let callState := EvmYul.Yul.State.mkOk (initial.initcall dispatcherDef.params []) - match EvmYul.Yul.exec fuel' (.Block dispatcherDef.body) (some contract) callState with - | .error err => .error err - | .ok finalState => - let restored := finalState.reviveJump.overwrite? initial |>.setStore initial - .ok (restored, List.map finalState.lookup! dispatcherDef.rets) + | _ => .error EvmYul.Yul.Exception.InvalidArguments) + | _ => .error EvmYul.Yul.Exception.InvalidArguments -/-- Dispatcher-block execution specialized to the lowered contract dispatcher - rather than the state-installed dispatcher lookup. +/-- Native primitive execution of the generated `retrieve()` scalar-return core: + `sload(0)` reads the materialized slot-zero word, then `mstore(0, value); + return(0, 32)` returns that exact word through the projected native result. -For states built by `initialState`, this is definitionally the next proof -target after `callDispatcherBlockResult`: native execution of the lowered -contract's dispatcher statement. -/ -def contractDispatcherBlockResult - (fuel' : Nat) +This composes the real EVMYulLean `SLOAD`, `MSTORE`, and `RETURN` primitive +relations for the SimpleStorage getter body, leaving only dispatcher selection +and oracle comparison around this selected-body path. -/ +theorem primCall_sload0_then_mstore0_return32_initialState_projectResult_returnValue + (sloadFuel mstoreFuel returnFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (initial : EvmYul.Yul.State) : - Except EvmYul.Yul.Exception - (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := - let dispatcherDef := - EvmYul.Yul.Ast.FunctionDefinition.Def [] [] [contract.dispatcher] - let callState := EvmYul.Yul.State.mkOk (initial.initcall dispatcherDef.params []) - match EvmYul.Yul.exec fuel' (.Block dispatcherDef.body) (some contract) callState with - | .error err => .error err - | .ok finalState => - let restored := finalState.reviveJump.overwrite? initial |>.setStore initial - .ok (restored, List.map finalState.lookup! dispatcherDef.rets) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hSlot : 0 ∈ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + ∃ haltState haltValue, + primCall_sload0_then_mstore0_return32_initialState + sloadFuel mstoreFuel returnFuel contract tx storage observableSlots = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = + some (uint256ToNat (storage 0)) := by + unfold primCall_sload0_then_mstore0_return32_initialState + rw [primCall_sload_initialState_observableSlot_ok sloadFuel contract tx storage + observableSlots 0 hSlot hRange] + generalize hload : + EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 0) = loaded + cases loaded with + | mk stateAfterLoad _ => + let sharedAfterLoad : EvmYul.SharedState .Yul := + { (initialState contract tx storage observableSlots).toSharedState with + toState := stateAfterLoad } + have hMemory : sharedAfterLoad.memory = ByteArray.empty := by + simp [sharedAfterLoad, initialState, EvmYul.Yul.State.toSharedState, + YulState.initial, toSharedState] + rcases + primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue + mstoreFuel returnFuel tx storage initialEvents sharedAfterLoad ∅ + (storage 0) hMemory with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, ?_, ?_⟩ + · simpa [sharedAfterLoad] using hExec + · simpa [natToUInt256, EvmYul.UInt256.toNat, uint256ToNat] using hReturn -/-- Raw native execution of the lowered contract dispatcher block, before the - `callDispatcher`-style state restoration and return-list projection. -/ -def contractDispatcherExecResult - (fuel' : Nat) +/-- Native primitive execution of the generated `retrieve()` scalar-return core + when slot zero was not materialized into the finite native storage map: + `sload(0)` returns the EVM zero word, and the following + `mstore(0, 0); return(0, 32)` projects as return value `0`. -/ +theorem primCall_sload0_then_mstore0_return32_initialState_omittedSlot_projectResult_returnValue + (sloadFuel mstoreFuel returnFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (initial : EvmYul.Yul.State) : - Except EvmYul.Yul.Exception EvmYul.Yul.State := - let dispatcherDef := - EvmYul.Yul.Ast.FunctionDefinition.Def [] [] [contract.dispatcher] - let callState := EvmYul.Yul.State.mkOk (initial.initcall dispatcherDef.params []) - EvmYul.Yul.exec fuel' (.Block dispatcherDef.body) (some contract) callState - -/-- Executing a singleton block whose only statement is another block is the - same as executing the inner block, after the outer block consumes its fuel - step. This is the structural wrapper around lowered contract dispatchers: - `contractDispatcherExecResult` installs `[contract.dispatcher]` as the - function body, while generated dispatcher lemmas reason about the lowered - block itself. -/ -theorem exec_singleton_block_eq_exec_block - (fuel : Nat) - (body : List EvmYul.Yul.Ast.Stmt) - (codeOverride : Option EvmYul.Yul.Ast.YulContract) - (state : EvmYul.Yul.State) : - EvmYul.Yul.exec (Nat.succ (Nat.succ fuel)) (.Block [.Block body]) - codeOverride state = - EvmYul.Yul.exec (Nat.succ fuel) (.Block body) codeOverride state := by - simp [EvmYul.Yul.exec] - cases EvmYul.Yul.exec (Nat.succ fuel) (.Block body) codeOverride state <;> - simp - -/-- Raw dispatcher execution for a lowered contract whose dispatcher is already - a block reduces to direct execution of that block from the native initial - switch state. This removes the function-call-frame wrapper from later - SimpleStorage dispatcher case proofs. -/ -theorem contractDispatcherExecResult_block_dispatcher_eq_exec_block - (fuel : Nat) - (body : List EvmYul.Yul.Ast.Stmt) - (functions : Compiler.Proofs.YulGeneration.Backends.NativeFunctionMap) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) : - contractDispatcherExecResult (Nat.succ (Nat.succ fuel)) - { dispatcher := .Block body, functions := functions } - (initialState { dispatcher := .Block body, functions := functions } tx - storage observableSlots) = - EvmYul.Yul.exec (Nat.succ fuel) (.Block body) - (some { dispatcher := .Block body, functions := functions }) - (nativeSwitchInitialOkState - { dispatcher := .Block body, functions := functions } tx storage - observableSlots) := by - have hCallState : - EvmYul.Yul.State.mkOk - ((initialState { dispatcher := .Block body, functions := functions } tx - storage observableSlots).initcall [] []) = - nativeSwitchInitialOkState - { dispatcher := .Block body, functions := functions } tx storage - observableSlots := by - simp [nativeSwitchInitialOkState, initialState, EvmYul.Yul.State.initcall, - EvmYul.Yul.State.setStore, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.mkOk] - constructor <;> rfl - unfold contractDispatcherExecResult - change - EvmYul.Yul.exec (Nat.succ (Nat.succ fuel)) (.Block [.Block body]) - (some { dispatcher := .Block body, functions := functions }) - (EvmYul.Yul.State.mkOk - ((initialState { dispatcher := .Block body, functions := functions } tx - storage observableSlots).initcall [] [])) = - EvmYul.Yul.exec (Nat.succ fuel) (.Block body) - (some { dispatcher := .Block body, functions := functions }) - (nativeSwitchInitialOkState - { dispatcher := .Block body, functions := functions } tx storage - observableSlots) - rw [hCallState] - exact exec_singleton_block_eq_exec_block fuel body - (some { dispatcher := .Block body, functions := functions }) - (nativeSwitchInitialOkState - { dispatcher := .Block body, functions := functions } tx storage - observableSlots) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hNotSlot : 0 ∉ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + ∃ haltState haltValue, + primCall_sload0_then_mstore0_return32_initialState + sloadFuel mstoreFuel returnFuel contract tx storage observableSlots = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = + some 0 := by + unfold primCall_sload0_then_mstore0_return32_initialState + rw [primCall_sload_initialState_omittedSlot_ok sloadFuel contract tx storage + observableSlots 0 hNotSlot hRange (by norm_num [EvmYul.UInt256.size])] + generalize hload : + EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 0) = loaded + cases loaded with + | mk stateAfterLoad _ => + let sharedAfterLoad : EvmYul.SharedState .Yul := + { (initialState contract tx storage observableSlots).toSharedState with + toState := stateAfterLoad } + have hMemory : sharedAfterLoad.memory = ByteArray.empty := by + simp [sharedAfterLoad, initialState, EvmYul.Yul.State.toSharedState, + YulState.initial, toSharedState] + rcases + primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue + mstoreFuel returnFuel tx storage initialEvents sharedAfterLoad ∅ + (natToUInt256 0) hMemory with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, ?_, ?_⟩ + · simpa [sharedAfterLoad] using hExec + · simpa [natToUInt256, EvmYul.UInt256.toNat, uint256ToNat] using hReturn -/-- The projected dispatcher-block result is just raw lowered-dispatcher - execution followed by the same restoration/projection used by - `callDispatcher`. -/ -theorem contractDispatcherBlockResult_eq_execResult - (fuel' : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (initial : EvmYul.Yul.State) : - contractDispatcherBlockResult fuel' contract initial = - let dispatcherDef := - EvmYul.Yul.Ast.FunctionDefinition.Def [] [] [contract.dispatcher] - match contractDispatcherExecResult fuel' contract initial with - | .error err => .error err - | .ok finalState => - let restored := finalState.reviveJump.overwrite? initial |>.setStore initial - .ok (restored, List.map finalState.lookup! dispatcherDef.rets) := by - simp [contractDispatcherBlockResult, contractDispatcherExecResult] +/-- Native primitive execution of the generated `retrieve()` scalar-return core, + with the slot-zero materialization split discharged internally. -/-- `initialState` installs the lowered contract as the execution contract, so - the dispatcher-block target can be rewritten to the lowered contract's own - dispatcher. -/ -theorem callDispatcherBlockResult_initialState_eq_contractDispatcherBlockResult - (fuel' : Nat) +If slot zero was materialized as observable native storage, the getter returns + the projected Verity storage word. If it was omitted from materialization, + EVMYulLean's `SLOAD` default-zero behavior is exposed as return value zero. + This theorem removes the caller-side `0 ∈ observableSlots`/`0 ∉ + observableSlots` premise split from the selected-body dispatcher proof. -/ +theorem primCall_sload0_then_mstore0_return32_initialState_projectResult_returnValue_materialized + (sloadFuel mstoreFuel returnFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) : - callDispatcherBlockResult fuel' contract - (initialState contract tx storage observableSlots) = - contractDispatcherBlockResult fuel' contract - (initialState contract tx storage observableSlots) := by - have hcode : - (initialState contract tx storage observableSlots).executionEnv.code = - contract := by - simp [initialState, EvmYul.Yul.State.executionEnv] - simp [callDispatcherBlockResult, contractDispatcherBlockResult, hcode] + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + ∃ haltState haltValue, + primCall_sload0_then_mstore0_return32_initialState + sloadFuel mstoreFuel returnFuel contract tx storage observableSlots = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = + if 0 ∈ observableSlots then + some (uint256ToNat (storage 0)) + else + some 0 := by + by_cases hSlot : 0 ∈ observableSlots + · rcases + primCall_sload0_then_mstore0_return32_initialState_projectResult_returnValue + sloadFuel mstoreFuel returnFuel contract tx storage initialEvents + observableSlots hSlot hRange with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, hExec, ?_⟩ + rw [if_pos hSlot] + simpa using hReturn + · rcases + primCall_sload0_then_mstore0_return32_initialState_omittedSlot_projectResult_returnValue + sloadFuel mstoreFuel returnFuel contract tx storage initialEvents + observableSlots hSlot hRange with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, hExec, ?_⟩ + rw [if_neg hSlot] + simpa using hReturn -@[simp] theorem callDispatcher_zero +/-- Native primitive execution of the generated `retrieve()` scalar-return core + from an arbitrary local store when slot zero is materialized. -/ +theorem primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_returnValue + (sloadFuel mstoreFuel returnFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (initial : EvmYul.Yul.State) : - EvmYul.Yul.callDispatcher 0 (some contract) initial = - .error EvmYul.Yul.Exception.OutOfFuel := by - simp [EvmYul.Yul.callDispatcher] + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (hSlot : 0 ∈ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + ∃ haltState haltValue, + primCall_sload0_then_mstore0_return32_initialState_withStore + sloadFuel mstoreFuel returnFuel contract tx storage observableSlots + store = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = + some (uint256ToNat (storage 0)) := by + unfold primCall_sload0_then_mstore0_return32_initialState_withStore + rw [primCall_sload_initialState_observableSlot_ok_withStore sloadFuel + contract tx storage observableSlots store 0 hSlot hRange] + generalize hload : + EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 0) = loaded + cases loaded with + | mk stateAfterLoad _ => + let initialWithStore : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + let sharedAfterLoad : EvmYul.SharedState .Yul := + { initialWithStore.toSharedState with toState := stateAfterLoad } + have hMemory : sharedAfterLoad.memory = ByteArray.empty := by + change initialWithStore.toSharedState.memory = ByteArray.empty + simp [initialWithStore, initialState, EvmYul.Yul.State.toSharedState, + EvmYul.Yul.State.sharedState, YulState.initial, toSharedState] + rcases + primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue + mstoreFuel returnFuel tx storage initialEvents sharedAfterLoad store + (storage 0) hMemory with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, ?_, ?_⟩ + · simpa [sharedAfterLoad, initialWithStore] using hExec + · simpa [natToUInt256, EvmYul.UInt256.toNat, uint256ToNat] using hReturn -/-- `callDispatcher` is exactly execution of the installed dispatcher block - once fuel and call-frame setup have been peeled away. -/ -theorem callDispatcher_succ_eq_callDispatcherBlockResult - (fuel' : Nat) +/-- Native primitive execution of the generated `retrieve()` scalar-return core + from an arbitrary local store when slot zero is omitted. -/ +theorem primCall_sload0_then_mstore0_return32_initialState_withStore_omittedSlot_projectResult_returnValue + (sloadFuel mstoreFuel returnFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) - (initial : EvmYul.Yul.State) : - EvmYul.Yul.callDispatcher (Nat.succ fuel') (some contract) initial = - callDispatcherBlockResult fuel' contract initial := by - simp [EvmYul.Yul.callDispatcher, callDispatcherBlockResult] - cases - EvmYul.Yul.exec fuel' - (.Block - (EvmYul.Yul.Ast.FunctionDefinition.Def [] [] - [initial.executionEnv.code.dispatcher]).body) - (some contract) - (EvmYul.Yul.State.mkOk - (initial.initcall - (EvmYul.Yul.Ast.FunctionDefinition.Def [] [] - [initial.executionEnv.code.dispatcher]).params [])) <;> rfl - -/-- Convert a native `callDispatcher` result to the current Verity observable - result shape. Reverts and hard native errors conservatively roll storage - back to the supplied initial storage function. -/ -def projectResult (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (result : - Except EvmYul.Yul.Exception - (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal)) : - YulResult := - match result with - | .ok (state, values) => - let finalStorage := projectStorageFromState tx state - { success := true - returnValue := values.head?.map uint256ToNat - finalStorage := finalStorage - finalMappings := Compiler.Proofs.storageAsMappings finalStorage - events := initialEvents ++ projectLogsFromState state } - | .error (.YulHalt state value) => - let finalStorage := projectStorageFromState tx state - { success := true - returnValue := projectHaltReturn state value - finalStorage := finalStorage - finalMappings := Compiler.Proofs.storageAsMappings finalStorage - events := initialEvents ++ projectLogsFromState state } - | .error _ => - { success := false - returnValue := none - finalStorage := initialStorage - finalMappings := Compiler.Proofs.storageAsMappings initialStorage - events := initialEvents } + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (hNotSlot : 0 ∉ observableSlots) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + ∃ haltState haltValue, + primCall_sload0_then_mstore0_return32_initialState_withStore + sloadFuel mstoreFuel returnFuel contract tx storage observableSlots + store = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = + some 0 := by + unfold primCall_sload0_then_mstore0_return32_initialState_withStore + rw [primCall_sload_initialState_omittedSlot_ok_withStore sloadFuel + contract tx storage observableSlots store 0 hNotSlot hRange + (by norm_num [EvmYul.UInt256.size])] + generalize hload : + EvmYul.State.sload + (initialState contract tx storage observableSlots).toState + (natToUInt256 0) = loaded + cases loaded with + | mk stateAfterLoad _ => + let initialWithStore : EvmYul.Yul.State := + .Ok (initialState contract tx storage observableSlots).sharedState store + let sharedAfterLoad : EvmYul.SharedState .Yul := + { initialWithStore.toSharedState with toState := stateAfterLoad } + have hMemory : sharedAfterLoad.memory = ByteArray.empty := by + change initialWithStore.toSharedState.memory = ByteArray.empty + simp [initialWithStore, initialState, EvmYul.Yul.State.toSharedState, + EvmYul.Yul.State.sharedState, YulState.initial, toSharedState] + rcases + primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue + mstoreFuel returnFuel tx storage initialEvents sharedAfterLoad store + (natToUInt256 0) hMemory with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, ?_, ?_⟩ + · simpa [sharedAfterLoad, initialWithStore] using hExec + · simpa [natToUInt256, EvmYul.UInt256.toNat, uint256ToNat] using hReturn -@[simp] theorem projectResult_ok +/-- Native primitive execution of the generated `retrieve()` scalar-return core + from an arbitrary local store, with materialized/omitted slot zero handled + internally. -/ +theorem primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_returnValue_materialized + (sloadFuel mstoreFuel returnFuel : Nat) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (values : List EvmYul.Yul.Ast.Literal) : - projectResult tx initialStorage initialEvents (.ok (state, values)) = - { success := true - returnValue := values.head?.map uint256ToNat - finalStorage := projectStorageFromState tx state - finalMappings := - Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) - events := initialEvents ++ projectLogsFromState state } := by - rfl - -/-- Exact projected result for native primitive execution of - `sstore(slot, value)` from an initial runtime shared state and arbitrary - dispatcher local-variable store. + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + ∃ haltState haltValue, + primCall_sload0_then_mstore0_return32_initialState_withStore + sloadFuel mstoreFuel returnFuel contract tx storage observableSlots + store = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + (projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = + if 0 ∈ observableSlots then + some (uint256ToNat (storage 0)) + else + some 0 := by + by_cases hSlot : 0 ∈ observableSlots + · rcases + primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_returnValue + sloadFuel mstoreFuel returnFuel contract tx storage initialEvents + observableSlots store hSlot hRange with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, hExec, ?_⟩ + rw [if_pos hSlot] + simpa using hReturn + · rcases + primCall_sload0_then_mstore0_return32_initialState_withStore_omittedSlot_projectResult_returnValue + sloadFuel mstoreFuel returnFuel contract tx storage initialEvents + observableSlots store hSlot hRange with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, hExec, ?_⟩ + rw [if_neg hSlot] + simpa using hReturn -This is the generic word-canonical `SSTORE` primitive result shape needed by -the dispatcher proof before the SimpleStorage setter composes it with -`CALLDATALOAD` and `STOP`. -/ -theorem primCall_sstore_initialState_wordSlot_withStore_projectResult_eq - (fuel : Nat) +/-- Exact projected result for the generated `retrieve()` scalar-return core + from an arbitrary dispatcher local store. This strengthens + `primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_returnValue_materialized` + from a return-value field fact to the full `YulResult` shape produced by the + native `SLOAD; MSTORE; RETURN` halt. -/ +theorem primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_eq_materialized + (sloadFuel mstoreFuel returnFuel : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) - (slot value : Nat) - (hSlotRange : slot < EvmYul.UInt256.size) : - ∃ finalState, - EvmYul.Yul.primCall (fuel + 1) - (.Ok (initialState contract tx storage observableSlots).sharedState store) - EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = - .ok (finalState, []) ∧ - projectResult tx storage initialEvents (.ok (finalState, [])) = + (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : + ∃ haltState haltValue, + primCall_sload0_then_mstore0_return32_initialState_withStore + sloadFuel mstoreFuel returnFuel contract tx storage observableSlots + store = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ + projectResult tx storage initialEvents + (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = { success := true - returnValue := none - finalStorage := projectStorageFromState tx finalState + returnValue := + if 0 ∈ observableSlots then + some (uint256ToNat (storage 0)) + else + some 0 + finalStorage := projectStorageFromState tx haltState finalMappings := - Compiler.Proofs.storageAsMappings (projectStorageFromState tx finalState) - events := initialEvents ++ projectLogsFromState finalState } := by - let initialWithStore : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - refine ⟨initialWithStore.setState - (initialWithStore.toState.sstore (natToUInt256 slot) (natToUInt256 value)), - ?_, ?_⟩ - · exact primCall_sstore_initialState_wordSlot_ok_withStore fuel contract tx - storage observableSlots store slot value hSlotRange - · simp [projectResult] + Compiler.Proofs.storageAsMappings (projectStorageFromState tx haltState) + events := initialEvents ++ projectLogsFromState haltState } := by + rcases + primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_returnValue_materialized + sloadFuel mstoreFuel returnFuel contract tx storage initialEvents + observableSlots store hRange with + ⟨haltState, haltValue, hExec, hReturn⟩ + refine ⟨haltState, haltValue, hExec, ?_⟩ + have hProjectReturn : + projectHaltReturn haltState haltValue = + if 0 ∈ observableSlots then + some (uint256ToNat (storage 0)) + else + some 0 := by + simpa [projectResult] using hReturn + simp [projectResult, hProjectReturn] -@[simp] theorem projectResult_yulHalt +@[simp] theorem projectResult_yulHalt_finalMappings (tx : YulTransaction) (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (state : EvmYul.Yul.State) (value : EvmYul.Yul.Ast.Literal) : - projectResult tx initialStorage initialEvents - (.error (.YulHalt state value)) = - { success := true - returnValue := projectHaltReturn state value - finalStorage := projectStorageFromState tx state - finalMappings := - Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) - events := initialEvents ++ projectLogsFromState state } := by - rfl - -@[simp] theorem projectResult_ok_events - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (values : List EvmYul.Yul.Ast.Literal) : - (projectResult tx initialStorage initialEvents (.ok (state, values))).events = - initialEvents ++ projectLogsFromState state := by - rfl - -@[simp] theorem projectResult_ok_success - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (values : List EvmYul.Yul.Ast.Literal) : - (projectResult tx initialStorage initialEvents - (.ok (state, values))).success = true := by - rfl - -@[simp] theorem projectResult_ok_returnValue - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (values : List EvmYul.Yul.Ast.Literal) : - (projectResult tx initialStorage initialEvents - (.ok (state, values))).returnValue = - values.head?.map uint256ToNat := by - rfl - -@[simp] theorem projectResult_ok_finalMappings - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (values : List EvmYul.Yul.Ast.Literal) : (projectResult tx initialStorage initialEvents - (.ok (state, values))).finalMappings = + (.error (.YulHalt state value))).finalMappings = Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) := by rfl -@[simp] theorem projectResult_ok_finalStorageSlot +@[simp] theorem projectResult_yulHalt_finalStorageSlot (tx : YulTransaction) (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (state : EvmYul.Yul.State) - (values : List EvmYul.Yul.Ast.Literal) + (value : EvmYul.Yul.Ast.Literal) (slot : Nat) (account : EvmYul.Account .Yul) - (value : EvmYul.UInt256) + (slotValue : EvmYul.UInt256) (hAccount : state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = some account) - (hSlot : account.storage.find? (natToUInt256 slot) = some value) : + (hSlot : account.storage.find? (natToUInt256 slot) = some slotValue) : (projectResult tx initialStorage initialEvents - (.ok (state, values))).finalStorage (IRStorageSlot.ofNat slot) = value := by + (.error (.YulHalt state value))).finalStorage (IRStorageSlot.ofNat slot) = + slotValue := by simp [projectResult, projectStorageFromState_accountStorageSlot, hAccount, hSlot] -@[simp] theorem projectResult_ok_missingFinalStorageAccountSlot +@[simp] theorem projectResult_yulHalt_missingFinalStorageAccountSlot (tx : YulTransaction) (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (state : EvmYul.Yul.State) - (values : List EvmYul.Yul.Ast.Literal) + (value : EvmYul.Yul.Ast.Literal) (slot : Nat) (hAccount : state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = none) : (projectResult tx initialStorage initialEvents - (.ok (state, values))).finalStorage (IRStorageSlot.ofNat slot) = 0 := by + (.error (.YulHalt state value))).finalStorage (IRStorageSlot.ofNat slot) = 0 := by simp [projectResult, projectStorageFromState_missingAccount, hAccount] -@[simp] theorem projectResult_ok_missingFinalStorageSlot +@[simp] theorem projectResult_yulHalt_missingFinalStorageSlot (tx : YulTransaction) (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (state : EvmYul.Yul.State) - (values : List EvmYul.Yul.Ast.Literal) + (value : EvmYul.Yul.Ast.Literal) (slot : Nat) (account : EvmYul.Account .Yul) (hAccount : @@ -11982,1779 +25054,8512 @@ theorem primCall_sstore_initialState_wordSlot_withStore_projectResult_eq some account) (hSlot : account.storage.find? (natToUInt256 slot) = none) : (projectResult tx initialStorage initialEvents - (.ok (state, values))).finalStorage (IRStorageSlot.ofNat slot) = 0 := by + (.error (.YulHalt state value))).finalStorage (IRStorageSlot.ofNat slot) = 0 := by simp [projectResult, projectStorageFromState_missingAccountStorageSlot, - hAccount, hSlot] - -/-- Native primitive execution of `sstore(slot, value)` on a word-canonical - initial runtime slot, lifted through Verity's projected native result - boundary for a nonzero write. - -This is the generic storage-projection form of the SimpleStorage slot-zero -setter lemma: it proves that the actual EVMYulLean `SSTORE` primitive writes -the projected final storage word for any canonical slot, as long as the EVM -storage update takes the insertion branch rather than the zero-value erasure -branch. -/ -theorem primCall_sstore_initialState_wordSlot_projectResult_slot - (fuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (observableSlots : List Nat) - (slot value : Nat) - (hSlotRange : slot < EvmYul.UInt256.size) - (hValueNonzero : - (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = false) : - ∃ finalState, - EvmYul.Yul.primCall (fuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = - .ok (finalState, []) ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = - natToUInt256 value := by - refine ⟨(initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (natToUInt256 slot) (natToUInt256 value)), ?_, ?_⟩ - · exact primCall_sstore_initialState_wordSlot_ok fuel contract tx storage - observableSlots slot value hSlotRange - · simp only [projectResult, projectStorageFromState, extractStorage, - initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, YulState.initial, toSharedState] - have hBranch : - (EvmYul.UInt256.ofNat value == (Inhabited.default : EvmYul.UInt256)) = - false := by - simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueNonzero - rw [hBranch] - simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ - Std.ReflCmp.compare_self] - -/-- Native primitive execution of `sstore(slot, 0)` on a word-canonical - initial runtime slot, lifted through Verity's projected native result - boundary with the EVMYulLean zero-write erasure lookup isolated. - -This is the zero-write companion to -`primCall_sstore_initialState_wordSlot_projectResult_slot`: it proves the -actual native `SSTORE` primitive path and leaves only the map-level fact that -erasing a key makes the projected lookup miss. -/ -theorem primCall_sstore_initialState_wordSlot_projectResult_slot_zero_of_erase - (fuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (observableSlots : List Nat) - (slot value : Nat) - (hSlotRange : slot < EvmYul.UInt256.size) - (hValueZero : - (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = true) : - ∃ finalState, - EvmYul.Yul.primCall (fuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = - .ok (finalState, []) ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = - 0 := by - refine ⟨(initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (natToUInt256 slot) (natToUInt256 value)), ?_, ?_⟩ - · exact primCall_sstore_initialState_wordSlot_ok fuel contract tx storage - observableSlots slot value hSlotRange - · simp only [projectResult, projectStorageFromState, extractStorage, - initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, YulState.initial, toSharedState, - natToUInt256] - have hBranch : - (EvmYul.UInt256.ofNat value == (Inhabited.default : EvmYul.UInt256)) = - true := by - simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueZero - rw [hBranch] - have hErase : - (Batteries.RBMap.erase (projectStorage storage observableSlots) - (natToUInt256 slot)).find? (natToUInt256 slot) = none := - Batteries.RBMap.find?_erase_self _ _ - simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ - Std.ReflCmp.compare_self, IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hErase] - -/-- Native primitive execution of `sstore(slot, 0)` on a word-canonical - initial runtime slot with no observable slots materialized. The zero-write - erasure lookup is discharged by computation at the generic `SSTORE` - projection boundary. -/ -theorem primCall_sstore_initialState_wordSlot_projectResult_slot_zero_emptyObservable - (fuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (slot value : Nat) - (hSlotRange : slot < EvmYul.UInt256.size) - (hValueZero : - (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = true) : - ∃ finalState, - EvmYul.Yul.primCall (fuel + 1) - (initialState contract tx storage []) - EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = - .ok (finalState, []) ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = - 0 := by - exact - primCall_sstore_initialState_wordSlot_projectResult_slot_zero_of_erase - fuel contract tx storage initialEvents [] slot value hSlotRange hValueZero - -/-- Native primitive execution of `sstore(slot, value)` from an initial runtime - shared state and arbitrary local-variable store, lifted through Verity's - projected native result boundary for a nonzero word-canonical write. This is - the generic dispatcher-local-store companion to - `primCall_sstore_initialState_wordSlot_projectResult_slot`. -/ -theorem primCall_sstore_initialState_wordSlot_withStore_projectResult_slot - (fuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) + hAccount, hSlot] + +@[simp] theorem projectResult_stop (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) + (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (slot value : Nat) - (hSlotRange : slot < EvmYul.UInt256.size) - (hValueNonzero : - (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = false) : - ∃ finalState, - EvmYul.Yul.primCall (fuel + 1) - (.Ok (initialState contract tx storage observableSlots).sharedState store) - EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = - .ok (finalState, []) ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = - natToUInt256 value := by - let initialWithStore : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - refine ⟨initialWithStore.setState - (initialWithStore.toState.sstore (natToUInt256 slot) (natToUInt256 value)), - ?_, ?_⟩ - · exact primCall_sstore_initialState_wordSlot_ok_withStore fuel contract tx - storage observableSlots store slot value hSlotRange - · dsimp [initialWithStore] - simp only [projectResult, projectStorageFromState, extractStorage, - initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, YulState.initial, toSharedState] - have hBranch : - (EvmYul.UInt256.ofNat value == (Inhabited.default : EvmYul.UInt256)) = - false := by - simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueNonzero - rw [hBranch] - simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ - Std.ReflCmp.compare_self] + (state : EvmYul.Yul.State) : + projectResult tx initialStorage initialEvents + (.error (.YulHalt state ⟨0⟩)) = + { success := true + returnValue := none + finalStorage := projectStorageFromState tx state + finalMappings := + Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) + events := initialEvents ++ projectLogsFromState state } := by + simp [projectResult] -/-- Native primitive execution of `sstore(slot, 0)` from an initial runtime - shared state and arbitrary local-variable store, lifted through Verity's - projected native result boundary with the zero-write erasure lookup - isolated. -/ -theorem primCall_sstore_initialState_wordSlot_withStore_projectResult_slot_zero_of_erase - (fuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) +@[simp] theorem projectResult_32ByteReturn (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) + (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (slot value : Nat) - (hSlotRange : slot < EvmYul.UInt256.size) - (hValueZero : - (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = true) : - ∃ finalState, - EvmYul.Yul.primCall (fuel + 1) - (.Ok (initialState contract tx storage observableSlots).sharedState store) - EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = - .ok (finalState, []) ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = - 0 := by - let initialWithStore : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - refine ⟨initialWithStore.setState - (initialWithStore.toState.sstore (natToUInt256 slot) (natToUInt256 value)), - ?_, ?_⟩ - · exact primCall_sstore_initialState_wordSlot_ok_withStore fuel contract tx - storage observableSlots store slot value hSlotRange - · dsimp [initialWithStore] - simp only [projectResult, projectStorageFromState, extractStorage, - initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, YulState.initial, toSharedState, - natToUInt256] - have hBranch : - (EvmYul.UInt256.ofNat value == (Inhabited.default : EvmYul.UInt256)) = - true := by - simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueZero - rw [hBranch] - have hErase : - (Batteries.RBMap.erase (projectStorage storage observableSlots) - (natToUInt256 slot)).find? (natToUInt256 slot) = none := - Batteries.RBMap.find?_erase_self _ _ - simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ - Std.ReflCmp.compare_self, IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hErase] + (state : EvmYul.Yul.State) + (value : EvmYul.Yul.Ast.Literal) + (hHalt : value ≠ ⟨0⟩) + (hSize : state.sharedState.H_return.size = 32) : + projectResult tx initialStorage initialEvents + (.error (.YulHalt state value)) = + { success := true + returnValue := some (byteArrayWord state.sharedState.H_return 0) + finalStorage := projectStorageFromState tx state + finalMappings := + Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) + events := initialEvents ++ projectLogsFromState state } := by + simp [projectResult, hHalt, hSize] -/-- Native primitive execution of `sstore(slot, 0)` from an arbitrary local - store when no observable storage (IRStorageSlot.ofNat slot)s were materialized. -/ -theorem primCall_sstore_initialState_wordSlot_withStore_projectResult_slot_zero_emptyObservable - (fuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) +@[simp] theorem projectResult_non32ByteReturn (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) + (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (store : EvmYul.Yul.VarStore) - (slot value : Nat) - (hSlotRange : slot < EvmYul.UInt256.size) - (hValueZero : - (natToUInt256 value == (⟨0⟩ : EvmYul.UInt256)) = true) : - ∃ finalState, - EvmYul.Yul.primCall (fuel + 1) - (.Ok (initialState contract tx storage []).sharedState store) - EvmYul.Operation.SSTORE [natToUInt256 slot, natToUInt256 value] = - .ok (finalState, []) ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat slot) = - 0 := by - exact - primCall_sstore_initialState_wordSlot_withStore_projectResult_slot_zero_of_erase - fuel contract tx storage initialEvents [] store slot value hSlotRange - hValueZero + (state : EvmYul.Yul.State) + (value : EvmYul.Yul.Ast.Literal) + (hHalt : value ≠ ⟨0⟩) + (hSize : state.sharedState.H_return.size ≠ 32) : + projectResult tx initialStorage initialEvents + (.error (.YulHalt state value)) = + { success := true + returnValue := some 0 + finalStorage := projectStorageFromState tx state + finalMappings := + Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) + events := initialEvents ++ projectLogsFromState state } := by + simp [projectResult, hHalt, hSize] -/-- Native primitive execution of the generated `store(uint256)` core, lifted - through Verity's projected native result boundary for call success and - absence of a return word. Storage-slot agreement remains the next setter - projection obligation, but callers no longer need to inspect the raw - `calldataload(4); sstore(0, arg0)` result shape for these fields. -/ -theorem primCall_calldataload4_then_sstore0_initialState_arg0_projectResult_ok - (loadFuel storeFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) +@[simp] theorem projectResult_revert (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (observableSlots : List Nat) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) : - ∃ finalState, - (do - let (state', values) ← - EvmYul.Yul.primCall (loadFuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] - match values with - | [value] => - EvmYul.Yul.primCall (storeFuel + 1) state' - EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .ok (finalState, []) ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).success = true ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).returnValue = - none := by - refine ⟨(initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)), ?_, ?_, ?_⟩ - · exact primCall_calldataload4_then_sstore0_initialState_arg0_ok - loadFuel storeFuel contract tx storage observableSlots arg rest hArgs - · rfl - · rfl + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) : + projectResult tx initialStorage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + { success := false + returnValue := none + finalStorage := initialStorage + finalMappings := Compiler.Proofs.storageAsMappings initialStorage + events := initialEvents } := by + rfl -/-- The native primitive sequence used by the generated SimpleStorage setter - body after dispatcher selection. -/ -def primCall_calldataload4_then_sstore0_stop_initialState_arg0 - (loadFuel storeFuel stopFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) +@[simp] theorem projectResult_revert_events (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) : - Except EvmYul.Yul.Exception - (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := do - let (state', values) ← - EvmYul.Yul.primCall (loadFuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] - match values with - | [value] => - (do - let (state'', values') ← - EvmYul.Yul.primCall (storeFuel + 1) state' - EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] - match values' with - | [] => - EvmYul.Yul.primCall (stopFuel + 1) state'' - EvmYul.Operation.STOP [] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) - | _ => .error EvmYul.Yul.Exception.InvalidArguments + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) : + (projectResult tx initialStorage initialEvents + (.error EvmYul.Yul.Exception.Revert)).events = + initialEvents := by + rfl -/-- Store-parametric form of the native primitive sequence used by the - generated SimpleStorage setter body. The lowered dispatcher executes the - selected body after adding switch temporaries to the Yul `VarStore`, while - calldata and storage effects are carried entirely by the shared state. -/ -def primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore - (loadFuel storeFuel stopFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) +@[simp] theorem projectResult_revert_success + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) : + (projectResult tx initialStorage initialEvents + (.error EvmYul.Yul.Exception.Revert)).success = false := by + rfl + +@[simp] theorem projectResult_revert_returnValue + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) : + (projectResult tx initialStorage initialEvents + (.error EvmYul.Yul.Exception.Revert)).returnValue = none := by + rfl + +@[simp] theorem projectResult_revert_finalMappings + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) : + (projectResult tx initialStorage initialEvents + (.error EvmYul.Yul.Exception.Revert)).finalMappings = + Compiler.Proofs.storageAsMappings initialStorage := by + rfl + +@[simp] theorem projectResult_revert_finalStorageSlot (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) : - Except EvmYul.Yul.Exception - (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := do - let (state', values) ← - EvmYul.Yul.primCall (loadFuel + 1) - (.Ok (initialState contract tx storage observableSlots).sharedState store) - EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] - match values with - | [value] => - (do - let (state'', values') ← - EvmYul.Yul.primCall (storeFuel + 1) state' - EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] - match values' with - | [] => - EvmYul.Yul.primCall (stopFuel + 1) state'' - EvmYul.Operation.STOP [] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) - | _ => .error EvmYul.Yul.Exception.InvalidArguments + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (slot : Nat) : + (projectResult tx initialStorage initialEvents + (.error EvmYul.Yul.Exception.Revert)).finalStorage (IRStorageSlot.ofNat slot) = + initialStorage (IRStorageSlot.ofNat slot) := by + rfl -/-- Exact native primitive execution shape for the generated SimpleStorage setter - body after dispatcher selection. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_eq - (loadFuel storeFuel stopFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) : - let finalState := - (initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) - primCall_calldataload4_then_sstore0_stop_initialState_arg0 - loadFuel storeFuel stopFuel contract tx storage observableSlots = - .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by - dsimp - unfold primCall_calldataload4_then_sstore0_stop_initialState_arg0 - rw [primCall_calldataload4_initialState_arg0_ok loadFuel contract tx - storage observableSlots arg rest hArgs] - change - (do - let (state'', values') ← - EvmYul.Yul.primCall (storeFuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.SSTORE - [EvmYul.UInt256.ofNat 0, natToUInt256 arg] - match values' with - | [] => - EvmYul.Yul.primCall (stopFuel + 1) state'' - EvmYul.Operation.STOP [] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .error (EvmYul.Yul.Exception.YulHalt - ((initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg))) ⟨0⟩) - rw [primCall_sstore_initialState_wordSlot_ok storeFuel contract tx storage - observableSlots 0 arg (by norm_num [EvmYul.UInt256.size])] - exact primCall_stop_ok stopFuel _ +@[simp] theorem projectResult_hardError + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (err : EvmYul.Yul.Exception) + (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : + projectResult tx initialStorage initialEvents (.error err) = + { success := false + returnValue := none + finalStorage := initialStorage + finalMappings := Compiler.Proofs.storageAsMappings initialStorage + events := initialEvents } := by + cases err with + | YulHalt state value => + exact False.elim (hNotHalt state value rfl) + | InvalidArguments => rfl + | NotEncodableRLP => rfl + | InvalidInstruction => rfl + | OutOfFuel => rfl + | StaticModeViolation => rfl + | MissingContract s => rfl + | MissingContractFunction s => rfl + | InvalidExpression => rfl + | YulEXTCODESIZENotImplemented => rfl + | Revert => rfl -/-- Exact native primitive execution shape for the generated SimpleStorage - setter body when the selected body starts with an arbitrary Yul - local-variable store. This removes the empty-store side condition left - around the dispatcher-selected setter path. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_eq - (loadFuel storeFuel stopFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) : - let initialWithStore : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - let finalState := - initialWithStore.setState - (initialWithStore.toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) - primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore - loadFuel storeFuel stopFuel contract tx storage observableSlots store = - .error (EvmYul.Yul.Exception.YulHalt finalState ⟨0⟩) := by - dsimp - unfold primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore - rw [primCall_calldataload4_initialState_arg0_ok_withStore loadFuel contract - tx storage observableSlots store arg rest hArgs] - change - (do - let (state'', values') ← - EvmYul.Yul.primCall (storeFuel + 1) - (.Ok (initialState contract tx storage observableSlots).sharedState store) - EvmYul.Operation.SSTORE - [EvmYul.UInt256.ofNat 0, natToUInt256 arg] - match values' with - | [] => - EvmYul.Yul.primCall (stopFuel + 1) state'' - EvmYul.Operation.STOP [] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .error (EvmYul.Yul.Exception.YulHalt - ((.Ok (initialState contract tx storage observableSlots).sharedState store : - EvmYul.Yul.State).setState - ((.Ok (initialState contract tx storage observableSlots).sharedState store : - EvmYul.Yul.State).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg))) ⟨0⟩) - rw [primCall_sstore_initialState_wordSlot_ok_withStore storeFuel contract tx - storage observableSlots store 0 arg (by norm_num [EvmYul.UInt256.size])] - exact primCall_stop_ok stopFuel _ +@[simp] theorem projectResult_hardError_success + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (err : EvmYul.Yul.Exception) + (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : + (projectResult tx initialStorage initialEvents (.error err)).success = false := by + cases err with + | YulHalt state value => + exact False.elim (hNotHalt state value rfl) + | InvalidArguments => rfl + | NotEncodableRLP => rfl + | InvalidInstruction => rfl + | OutOfFuel => rfl + | StaticModeViolation => rfl + | MissingContract s => rfl + | MissingContractFunction s => rfl + | InvalidExpression => rfl + | YulEXTCODESIZENotImplemented => rfl + | Revert => rfl -/-- Native primitive execution of the full generated `store(uint256)` selected - body from an arbitrary local store, lifted through the terminating `STOP` - halt and Verity's projected native result boundary for call success and - absence of a return word. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_ok - (loadFuel storeFuel stopFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) +@[simp] theorem projectResult_hardError_returnValue + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) : - ∃ haltState haltValue, - primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore - loadFuel storeFuel stopFuel contract tx storage observableSlots store = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).success = - true ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = - none := by - let initialWithStore : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - let finalState := - initialWithStore.setState - (initialWithStore.toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) - refine ⟨finalState, ⟨0⟩, ?_, ?_, ?_⟩ - · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_eq - loadFuel storeFuel stopFuel contract tx storage observableSlots store arg - rest hArgs - · rfl - · rfl + (err : EvmYul.Yul.Exception) + (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : + (projectResult tx initialStorage initialEvents (.error err)).returnValue = none := by + cases err with + | YulHalt state value => + exact False.elim (hNotHalt state value rfl) + | InvalidArguments => rfl + | NotEncodableRLP => rfl + | InvalidInstruction => rfl + | OutOfFuel => rfl + | StaticModeViolation => rfl + | MissingContract s => rfl + | MissingContractFunction s => rfl + | InvalidExpression => rfl + | YulEXTCODESIZENotImplemented => rfl + | Revert => rfl -/-- Exact projected result for the generated `store(uint256)` selected body - from an arbitrary dispatcher local store. This packages the - `CALLDATALOAD; SSTORE; STOP` native primitive sequence as one full - `YulResult` equality, rather than only exposing success and return-value - field facts. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_eq - (loadFuel storeFuel stopFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) +@[simp] theorem projectResult_hardError_finalStorageSlot + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) : - ∃ haltState haltValue, - primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore - loadFuel storeFuel stopFuel contract tx storage observableSlots store = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = - { success := true - returnValue := none - finalStorage := projectStorageFromState tx haltState - finalMappings := - Compiler.Proofs.storageAsMappings (projectStorageFromState tx haltState) - events := initialEvents ++ projectLogsFromState haltState } := by - let initialWithStore : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - let finalState := - initialWithStore.setState - (initialWithStore.toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) - refine ⟨finalState, ⟨0⟩, ?_, ?_⟩ - · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_eq - loadFuel storeFuel stopFuel contract tx storage observableSlots store arg - rest hArgs - · simp [projectResult] + (err : EvmYul.Yul.Exception) + (slot : Nat) + (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : + (projectResult tx initialStorage initialEvents (.error err)).finalStorage (IRStorageSlot.ofNat slot) = + initialStorage (IRStorageSlot.ofNat slot) := by + cases err with + | YulHalt state value => + exact False.elim (hNotHalt state value rfl) + | InvalidArguments => rfl + | NotEncodableRLP => rfl + | InvalidInstruction => rfl + | OutOfFuel => rfl + | StaticModeViolation => rfl + | MissingContract s => rfl + | MissingContractFunction s => rfl + | InvalidExpression => rfl + | YulEXTCODESIZENotImplemented => rfl + | Revert => rfl -/-- Exact projected result for the generated `store(uint256)` selected body at - the IR transaction boundary used by the end-to-end native theorem. This is - the `YulTransaction.ofIR` specialization of the dispatcher-local - `CALLDATALOAD; SSTORE; STOP` native primitive sequence. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_ofIR_arg0_withStore_projectResult_eq - (loadFuel storeFuel stopFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : Compiler.Proofs.IRGeneration.IRTransaction) - (storage : IRStorageSlot → IRStorageWord) +@[simp] theorem projectResult_hardError_finalMappings + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) : - ∃ haltState haltValue, - primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore - loadFuel storeFuel stopFuel contract (YulTransaction.ofIR tx) storage - observableSlots store = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - projectResult (YulTransaction.ofIR tx) storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = - { success := true - returnValue := none - finalStorage := projectStorageFromState (YulTransaction.ofIR tx) haltState - finalMappings := - Compiler.Proofs.storageAsMappings - (projectStorageFromState (YulTransaction.ofIR tx) haltState) - events := initialEvents ++ projectLogsFromState haltState } := by - exact - primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_eq - loadFuel storeFuel stopFuel contract (YulTransaction.ofIR tx) storage - initialEvents observableSlots store arg rest (by simpa using hArgs) + (err : EvmYul.Yul.Exception) + (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : + (projectResult tx initialStorage initialEvents (.error err)).finalMappings = + Compiler.Proofs.storageAsMappings initialStorage := by + cases err with + | YulHalt state value => + exact False.elim (hNotHalt state value rfl) + | InvalidArguments => rfl + | NotEncodableRLP => rfl + | InvalidInstruction => rfl + | OutOfFuel => rfl + | StaticModeViolation => rfl + | MissingContract s => rfl + | MissingContractFunction s => rfl + | InvalidExpression => rfl + | YulEXTCODESIZENotImplemented => rfl + | Revert => rfl -/-- Native primitive execution of the full generated `store(uint256)` selected - body from an arbitrary local store, lifted through `STOP` and Verity's - projected native result boundary for a nonzero slot-zero write. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_slot0 - (loadFuel storeFuel stopFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) +@[simp] theorem projectResult_hardError_events + (tx : YulTransaction) + (initialStorage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) - (hValueNonzero : - (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = false) : - ∃ haltState haltValue, - primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore - loadFuel storeFuel stopFuel contract tx storage observableSlots store = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = - natToUInt256 arg := by - let initialWithStore : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - let finalState := - initialWithStore.setState - (initialWithStore.toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) - refine ⟨finalState, ⟨0⟩, ?_, ?_⟩ - · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_eq - loadFuel storeFuel stopFuel contract tx storage observableSlots store arg - rest hArgs - · dsimp [finalState, initialWithStore] - simp only [projectResult, projectStorageFromState, extractStorage, - initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, YulState.initial, toSharedState] - have hBranch : - (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = - false := by - simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueNonzero - rw [hBranch] - simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ - Std.ReflCmp.compare_self] + (err : EvmYul.Yul.Exception) + (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : + (projectResult tx initialStorage initialEvents (.error err)).events = + initialEvents := by + cases err with + | YulHalt state value => + exact False.elim (hNotHalt state value rfl) + | InvalidArguments => rfl + | NotEncodableRLP => rfl + | InvalidInstruction => rfl + | OutOfFuel => rfl + | StaticModeViolation => rfl + | MissingContract s => rfl + | MissingContractFunction s => rfl + | InvalidExpression => rfl + | YulEXTCODESIZENotImplemented => rfl + | Revert => rfl -/-- Zero-write storage projection for the full generated `store(uint256)` - selected body from an arbitrary local store, through the terminating - `STOP`, with the remaining RBMap erasure fact isolated. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_slot0_zero_of_erase - (loadFuel storeFuel stopFuel : Nat) +/-- Guarded selector-hit execution for a fully lowered native switch block, + with the projected selected-body error result exposed at the same switch + boundary. + +Callers prove the selected body reaches the native error or halt and packages +its `projectResult`; this lemma lifts both facts through the generated +selector-switch wrapper. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody : List EvmYul.Yul.Ast.Stmt) + (tag : Nat) + (body : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) - (hValueZero : - (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : - ∃ haltState haltValue, - primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore - loadFuel storeFuel stopFuel contract tx storage observableSlots store = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = - 0 := by - let initialWithStore : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - let finalState := - initialWithStore.setState - (initialWithStore.toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) - refine ⟨finalState, ⟨0⟩, ?_, ?_⟩ - · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_eq - loadFuel storeFuel stopFuel contract tx storage observableSlots store arg - rest hArgs - · dsimp [finalState, initialWithStore] - simp only [projectResult, projectStorageFromState, extractStorage, - initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, YulState.initial, toSharedState, - natToUInt256] - have hBranch : - (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = - true := by - simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueZero - rw [hBranch] - have hErase : - (Batteries.RBMap.erase (projectStorage storage observableSlots) - (EvmYul.UInt256.ofNat 0)).find? (EvmYul.UInt256.ofNat 0) = none := - Batteries.RBMap.find?_erase_self _ _ - simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ - Std.ReflCmp.compare_self, IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hErase] + (err : EvmYul.Yul.Exception) + (nativeYul : YulResult) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) + (nativeSwitchMarkedPrefixStateForId contract tx storage + observableSlots switchId) = .error err) + (hProject : projectResult tx storage initialEvents (.error err) = nativeYul) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .error err ∧ + projectResult tx storage initialEvents (.error err) = nativeYul := by + refine ⟨?_, hProject⟩ + exact exec_lowerNativeSwitchBlock_selector_find_hit_error_fuel + fuel selector switchId cases defaultBody tag body contract tx storage + observableSlots err hSelector hFind hSelectorRange hTagsRange + (by + intro pre suffix hCases + simpa [nativeSwitchMarkedPrefixStateForId, nativeSwitchPrefixStateForId] + using hBody pre suffix hCases) -/-- Zero-write storage projection for the full generated `store(uint256)` - selected body from an arbitrary local store when no observable slots were - materialized. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_slot0_zero_emptyObservable - (loadFuel storeFuel stopFuel : Nat) +/-- Store-parametric selector-hit projection for lowered native switches. + +This is the projection form used when a generated dispatcher has already +installed additional local bindings before entering the selector switch. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) + (observableSlots : List Nat) (store : EvmYul.Yul.VarStore) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) - (hValueZero : - (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : - ∃ haltState haltValue, - primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore - loadFuel storeFuel stopFuel contract tx storage [] store = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = - 0 := by - exact - primCall_calldataload4_then_sstore0_stop_initialState_arg0_withStore_projectResult_slot0_zero_of_erase - loadFuel storeFuel stopFuel contract tx storage initialEvents [] store arg - rest hArgs hValueZero - -/-- Native primitive execution of the full generated `store(uint256)` selected - body tail: `calldataload(4); sstore(0, arg0); stop`. The terminating - `STOP` travels through EVMYulLean's Yul-halt channel and projects as a - successful call with no return word. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_projectResult_ok - (loadFuel storeFuel stopFuel : Nat) + (err : EvmYul.Yul.Exception) + (nativeYul : YulResult) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots switchId store) = .error err) + (hProject : projectResult tx storage initialEvents (.error err) = nativeYul) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (.Ok (initialState contract tx storage observableSlots).sharedState store) = + .error err ∧ + projectResult tx storage initialEvents (.error err) = nativeYul := by + refine ⟨?_, hProject⟩ + exact exec_lowerNativeSwitchBlock_selector_find_hit_error_store_fuel + fuel selector switchId tag cases defaultBody body contract tx storage + observableSlots store err hSelector hFind hSelectorRange hTagsRange + (by + intro pre suffix hCases + simpa [nativeSwitchStoreMarkedPrefixStateForId] + using hBody pre suffix hCases) + +/-- Store-parametric selector-hit projection for a payable generated case body, + with the generated comment and calldata-size guard discharged before the + selected user body premise. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq_payable_generated_prefix + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) : - ∃ haltState haltValue, - primCall_calldataload4_then_sstore0_stop_initialState_arg0 - loadFuel storeFuel stopFuel contract tx storage observableSlots = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).success = - true ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = - none := by - let finalState := - (initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) - refine ⟨finalState, ⟨0⟩, ?_, ?_, ?_⟩ - · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_eq - loadFuel storeFuel stopFuel contract tx storage observableSlots arg rest - hArgs - · rfl - · rfl - -/-- Native primitive execution of the full generated `store(uint256)` selected - body, lifted through the terminating `STOP` halt and Verity's projected - native result boundary for a nonzero slot-zero write. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_projectResult_slot0 - (loadFuel storeFuel stopFuel : Nat) + (store : EvmYul.Yul.VarStore) + (err : EvmYul.Yul.Exception) + (nativeYul : YulResult) + (reservedNames : List String) (n0 next : Nat) + (fn : IRFunction) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (body, next)) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) ∧ + ((∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId store) = + .error err) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul → + EvmYul.Yul.exec (fuel + cases.length + 16) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + defaultBody) + (some contract) + (.Ok + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots).sharedState store) = + .error err ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul) := by + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames n0 fn body next hPayable hLower with + ⟨guardBody, bodyNative, bodyStart, hBodyShape, hBodyLower⟩ + refine ⟨bodyNative, bodyStart, hBodyLower, ?_⟩ + intro hBodyNative hProject + have hExec := + exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq + (fuel + 4) selector switchId tag cases defaultBody body contract + (YulTransaction.ofIR tx) storage initialEvents observableSlots store err + nativeYul hSelector hFind hSelectorRange hTagsRange + (by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := exec_switchCaseBody_payable_prefix_eq + (fuel + suffix.length + 1) guardBody bodyNative contract + (YulTransaction.ofIR tx) storage observableSlots switchId store + (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + (by simp; omega) + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + hPrefix.trans (hBodyNative pre suffix hCases)) + hProject + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hExec + +/-- Store-parametric selector-hit projection for a non-payable generated case + body, with the generated comment, callvalue guard, and calldata-size guard + discharged before the selected user body premise. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq_nonpayable_generated_prefix + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) - (hValueNonzero : - (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = false) : - ∃ haltState haltValue, - primCall_calldataload4_then_sstore0_stop_initialState_arg0 - loadFuel storeFuel stopFuel contract tx storage observableSlots = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = - natToUInt256 arg := by - let finalState := - (initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) - refine ⟨finalState, ⟨0⟩, ?_, ?_⟩ - · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_eq - loadFuel storeFuel stopFuel contract tx storage observableSlots arg rest - hArgs - · dsimp [finalState] - simp only [projectResult, projectStorageFromState, extractStorage, - initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, YulState.initial, toSharedState] - have hBranch : - (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = - false := by - simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueNonzero - rw [hBranch] - simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ - Std.ReflCmp.compare_self] - -/-- Zero-write storage projection for the full generated `store(uint256)` selected - body through the terminating `STOP`, with the remaining RBMap erasure fact - isolated at the same boundary as the non-terminating setter-core lemma. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_projectResult_slot0_zero_of_erase - (loadFuel storeFuel stopFuel : Nat) + (store : EvmYul.Yul.VarStore) + (err : EvmYul.Yul.Exception) + (nativeYul : YulResult) + (reservedNames : List String) (n0 next : Nat) + (fn : IRFunction) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (body, next)) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) ∧ + ((∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId store) = + .error err) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul → + EvmYul.Yul.exec (fuel + cases.length + 17) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + defaultBody) + (some contract) + (.Ok + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots).sharedState store) = + .error err ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul) := by + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames n0 fn body next hNonPayable hLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, bodyStart, + hBodyShape, hBodyLower⟩ + refine ⟨bodyNative, bodyStart, hBodyLower, ?_⟩ + intro hBodyNative hProject + have hExec := + exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq + (fuel + 5) selector switchId tag cases defaultBody body contract + (YulTransaction.ofIR tx) storage initialEvents observableSlots store err + nativeYul hSelector hFind hSelectorRange hTagsRange + (by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := exec_switchCaseBody_nonpayable_prefix_eq + (fuel + suffix.length + 1) callvalueGuardBody calldataGuardBody + bodyNative contract (YulTransaction.ofIR tx) storage observableSlots + switchId store (4 + fn.params.length * 32) + (DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable fn tx hguards + hNonPayable) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + (by simp; omega) + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + hPrefix.trans (hBodyNative pre suffix hCases)) + hProject + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hExec + +/-- Store-parametric selector-hit success projection for a payable generated + case body. The generated prefix is discharged before the lowered user body, + and matched preservation is required only for that user body. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq_payable_generated_prefix + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) + (tx : IRTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) - (hValueZero : - (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : - ∃ haltState haltValue, - primCall_calldataload4_then_sstore0_stop_initialState_arg0 - loadFuel storeFuel stopFuel contract tx storage observableSlots = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = - 0 := by - let finalState := - (initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)) - refine ⟨finalState, ⟨0⟩, ?_, ?_⟩ - · exact primCall_calldataload4_then_sstore0_stop_initialState_arg0_eq - loadFuel storeFuel stopFuel contract tx storage observableSlots arg rest - hArgs - · dsimp [finalState] - simp only [projectResult, projectStorageFromState, extractStorage, - initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, YulState.initial, toSharedState, - natToUInt256] - have hBranch : - (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = - true := by - simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueZero - rw [hBranch] - have hErase : - (Batteries.RBMap.erase (projectStorage storage observableSlots) - (EvmYul.UInt256.ofNat 0)).find? (EvmYul.UInt256.ofNat 0) = none := - Batteries.RBMap.find?_erase_self _ _ - simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ - Std.ReflCmp.compare_self, IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hErase] - -/-- Zero-write storage projection for the full generated `store(uint256)` selected - body through `STOP` when no observable slots were materialized. -/ -theorem primCall_calldataload4_then_sstore0_stop_initialState_arg0_projectResult_slot0_zero_emptyObservable - (loadFuel storeFuel stopFuel : Nat) + (store : EvmYul.Yul.VarStore) + (final : EvmYul.Yul.State) + (nativeYul : YulResult) + (reservedNames : List String) (n0 next : Nat) + (fn : IRFunction) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (body, next)) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) ∧ + ((∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId store) = + .ok final) → + (∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + EvmYul.Yul.exec (fuel + cases.length + 16) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + defaultBody) + (some contract) + (.Ok + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots).sharedState store) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames n0 fn body next hPayable hLower with + ⟨guardBody, bodyNative, bodyStart, hBodyShape, hBodyLower⟩ + refine ⟨bodyNative, bodyStart, hBodyLower, ?_⟩ + intro hBodyNative hPreservesNative hProject + have hExec := + exec_lowerNativeSwitchBlock_selector_find_hit_finalMatched_store_fuel + (fuel + 4) selector switchId tag cases defaultBody body contract + (YulTransaction.ofIR tx) storage observableSlots store final hSelector + hFind hSelectorRange hTagsRange + (by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := exec_switchCaseBody_payable_prefix_eq + (fuel + suffix.length + 1) guardBody bodyNative contract + (YulTransaction.ofIR tx) storage observableSlots switchId store + (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + (by simp; omega) + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + hPrefix.trans (hBodyNative pre suffix hCases)) + (by + intro matchedName hMatchedName + subst matchedName + rcases nativeSwitch_find_hit_split selector cases tag body hFind with + ⟨pre, suffix, hCases, _hTag, _hPrefix⟩ + exact hPreservesNative pre suffix hCases + (fuel + suffix.length + 10) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId store) + final + (nativeSwitchStoreMarkedPrefixStateForId_matched contract + (YulTransaction.ofIR tx) storage observableSlots switchId store + (Backends.nativeSwitchMatchedTempName switchId) rfl) + (hBodyNative pre suffix hCases)) + exact ⟨by + simpa [nativeSwitchStoreInitialState, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hExec, hProject⟩ + +/-- Store-parametric selector-hit success projection for a non-payable + generated case body. The generated prefix is discharged before the lowered + user body, and matched preservation is required only for that user body. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq_nonpayable_generated_prefix + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) + (tx : IRTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) - (hValueZero : - (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : - ∃ haltState haltValue, - primCall_calldataload4_then_sstore0_stop_initialState_arg0 - loadFuel storeFuel stopFuel contract tx storage [] = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).finalStorage (IRStorageSlot.ofNat 0) = - 0 := by - exact - primCall_calldataload4_then_sstore0_stop_initialState_arg0_projectResult_slot0_zero_of_erase - loadFuel storeFuel stopFuel contract tx storage initialEvents [] arg rest - hArgs hValueZero - -/-- Native primitive execution of the generated `store(uint256)` core, lifted - through Verity's projected native result boundary for a nonzero slot-zero - write. The remaining zero-write case goes through `Account.updateStorage`'s - key-erasure branch and needs the corresponding `RBMap.erase` lookup fact. -/ -theorem primCall_calldataload4_then_sstore0_initialState_arg0_projectResult_slot0 - (loadFuel storeFuel : Nat) + (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) + (final : EvmYul.Yul.State) + (nativeYul : YulResult) + (reservedNames : List String) (n0 next : Nat) + (fn : IRFunction) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (body, next)) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) ∧ + ((∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId store) = + .ok final) → + (∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + EvmYul.Yul.exec (fuel + cases.length + 17) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + defaultBody) + (some contract) + (.Ok + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots).sharedState store) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames n0 fn body next hNonPayable hLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, bodyStart, + hBodyShape, hBodyLower⟩ + refine ⟨bodyNative, bodyStart, hBodyLower, ?_⟩ + intro hBodyNative hPreservesNative hProject + have hExec := + exec_lowerNativeSwitchBlock_selector_find_hit_finalMatched_store_fuel + (fuel + 5) selector switchId tag cases defaultBody body contract + (YulTransaction.ofIR tx) storage observableSlots store final hSelector + hFind hSelectorRange hTagsRange + (by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := exec_switchCaseBody_nonpayable_prefix_eq + (fuel + suffix.length + 1) callvalueGuardBody calldataGuardBody + bodyNative contract (YulTransaction.ofIR tx) storage observableSlots + switchId store (4 + fn.params.length * 32) + (DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable fn tx hguards + hNonPayable) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + (by simp; omega) + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + hPrefix.trans (hBodyNative pre suffix hCases)) + (by + intro matchedName hMatchedName + subst matchedName + rcases nativeSwitch_find_hit_split selector cases tag body hFind with + ⟨pre, suffix, hCases, _hTag, _hPrefix⟩ + exact hPreservesNative pre suffix hCases + (fuel + suffix.length + 10) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId store) + final + (nativeSwitchStoreMarkedPrefixStateForId_matched contract + (YulTransaction.ofIR tx) storage observableSlots switchId store + (Backends.nativeSwitchMatchedTempName switchId) rfl) + (hBodyNative pre suffix hCases)) + exact ⟨by + simpa [nativeSwitchStoreInitialState, Nat.add_assoc, Nat.add_comm, + Nat.add_left_comm] using hExec, hProject⟩ + +/-- Store-parametric selector-miss projection for lowered native switches. + +This is the miss-case companion to +`exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq`, +used when earlier dispatcher-local bindings are present before the selector +switch falls through to `revert(0, 0)`. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_projectResult_eq + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) - (hValueNonzero : - (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = false) : - ∃ finalState, - (do - let (state', values) ← - EvmYul.Yul.primCall (loadFuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] - match values with - | [value] => - EvmYul.Yul.primCall (storeFuel + 1) state' - EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .ok (finalState, []) ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat 0) = - natToUInt256 arg := by - refine ⟨(initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)), ?_, ?_⟩ - · exact primCall_calldataload4_then_sstore0_initialState_arg0_ok - loadFuel storeFuel contract tx storage observableSlots arg rest hArgs - · simp only [projectResult, projectStorageFromState, extractStorage, - initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, YulState.initial, toSharedState] - have hBranch : - (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = - false := by - simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueNonzero - rw [hBranch] - simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ - Std.ReflCmp.compare_self] - -/-- Zero `sstore` projection, with the remaining RBMap erasure fact isolated. -/ -theorem primCall_calldataload4_then_sstore0_initialState_arg0_projectResult_slot0_zero_of_erase - (loadFuel storeFuel : Nat) + (store : EvmYul.Yul.VarStore) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + [nativeRevertZeroZeroStmt]) + (some contract) + (.Ok (initialState contract tx storage observableSlots).sharedState store) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + { success := false + returnValue := none + finalStorage := storage + finalMappings := Compiler.Proofs.storageAsMappings storage + events := initialEvents } := by + refine ⟨?_, by simp⟩ + exact exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_fuel + fuel selector switchId cases contract tx storage observableSlots store + hSelector hFind hSelectorRange hTagsRange + +/-- Bridge-shape selector-miss projection on the post-`__has_selector := 1` + state. This packages both the block-level native `Revert` endpoint and + the exact projected rollback result. -/ +theorem exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_projectResult_eq + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) - (hValueZero : - (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : - ∃ finalState, - (do - let (state', values) ← - EvmYul.Yul.primCall (loadFuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] - match values with - | [value] => - EvmYul.Yul.primCall (storeFuel + 1) state' - EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .ok (finalState, []) ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat 0) = - 0 := by - refine ⟨(initialState contract tx storage observableSlots).setState - ((initialState contract tx storage observableSlots).toState.sstore - (EvmYul.UInt256.ofNat 0) (natToUInt256 arg)), ?_, ?_⟩ - · exact primCall_calldataload4_then_sstore0_initialState_arg0_ok - loadFuel storeFuel contract tx storage observableSlots arg rest hArgs - · simp only [projectResult, projectStorageFromState, extractStorage, - initialState, EvmYul.Yul.State.sharedState, EvmYul.Yul.State.setState, - EvmYul.Yul.State.toState, EvmYul.State.sstore, EvmYul.State.lookupAccount, - EvmYul.State.setAccount, EvmYul.State.addAccessedStorageKey, - EvmYul.Account.updateStorage, YulState.initial, toSharedState, - natToUInt256] - have hBranch : - (EvmYul.UInt256.ofNat arg == (Inhabited.default : EvmYul.UInt256)) = - true := by - simpa [natToUInt256, EvmYul.UInt256.instInhabited] using hValueZero - rw [hBranch] - have hErase : - (Batteries.RBMap.erase (projectStorage storage observableSlots) - (EvmYul.UInt256.ofNat 0)).find? (EvmYul.UInt256.ofNat 0) = none := - Batteries.RBMap.find?_erase_self _ _ - simp [Option.option, Batteries.RBMap.find?_insert_of_eq _ - Std.ReflCmp.compare_self, IRStorageSlot.toUInt256, IRStorageSlot.ofNat, hErase] + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 13) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + { success := false + returnValue := none + finalStorage := storage + finalMappings := Compiler.Proofs.storageAsMappings storage + events := initialEvents } := by + rcases + exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_projectResult_eq + fuel selector switchId cases contract tx storage initialEvents + observableSlots nativeSwitchHasSelectorStore hSelector hFind + hSelectorRange hTagsRange with + ⟨hEndpoint, hProject⟩ + have hFuelEq : fuel + cases.length + 13 = (fuel + cases.length + 12).succ := by + omega + rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] + refine ⟨?_, hProject⟩ + exact exec_block_cons_error (fuel + cases.length + 12) _ [] _ _ + EvmYul.Yul.Exception.Revert hEndpoint -/-- Zero `sstore` projection with empty observable-slot materialization. -/ -theorem primCall_calldataload4_then_sstore0_initialState_arg0_projectResult_slot0_zero_emptyObservable - (loadFuel storeFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) +/-- Bridge-shape selector-hit error projection on the post-`__has_selector := 1` + state. This packages a selected body halt/error with its projected result + after the generated dispatcher-local binding has been installed. -/ +theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (arg : Nat) - (rest : List Nat) - (hArgs : tx.args = arg :: rest) - (hValueZero : - (natToUInt256 arg == (⟨0⟩ : EvmYul.UInt256)) = true) : - ∃ finalState, - (do - let (state', values) ← - EvmYul.Yul.primCall (loadFuel + 1) - (initialState contract tx storage []) - EvmYul.Operation.CALLDATALOAD [EvmYul.UInt256.ofNat 4] - match values with - | [value] => - EvmYul.Yul.primCall (storeFuel + 1) state' - EvmYul.Operation.SSTORE [EvmYul.UInt256.ofNat 0, value] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .ok (finalState, []) ∧ - (projectResult tx storage initialEvents (.ok (finalState, []))).finalStorage (IRStorageSlot.ofNat 0) = - 0 := by - exact - primCall_calldataload4_then_sstore0_initialState_arg0_projectResult_slot0_zero_of_erase - loadFuel storeFuel contract tx storage initialEvents [] arg rest hArgs - hValueZero + (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) + (nativeYul : YulResult) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx + storage observableSlots switchId nativeSwitchHasSelectorStore) = + .error err) + (hProject : projectResult tx storage initialEvents (.error err) = nativeYul) : + EvmYul.Yul.exec (fuel + cases.length + 13) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) = .error err ∧ + projectResult tx storage initialEvents (.error err) = nativeYul := by + rcases exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq + fuel selector switchId tag cases defaultBody body contract tx storage + initialEvents observableSlots nativeSwitchHasSelectorStore err nativeYul + hSelector hFind hSelectorRange hTagsRange hBody hProject with + ⟨hEndpoint, hProject'⟩ + have hFuelEq : fuel + cases.length + 13 = (fuel + cases.length + 12).succ := by + omega + rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] + exact ⟨exec_block_cons_error (fuel + cases.length + 12) _ [] _ _ err hEndpoint, + hProject'⟩ -@[simp] theorem projectResult_yulHalt_events - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) +/-- Bridge-shape selector-hit error projection for a payable generated case on + the post-`__has_selector := 1` state, with generated case guards discharged + before the selected user body premise. -/ +theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq_payable_generated_prefix + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (value : EvmYul.Yul.Ast.Literal) : - (projectResult tx initialStorage initialEvents - (.error (.YulHalt state value))).events = - initialEvents ++ projectLogsFromState state := by - rfl + (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) + (nativeYul : YulResult) + (reservedNames : List String) (n0 next : Nat) + (fn : IRFunction) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (body, next)) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) ∧ + ((∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId + nativeSwitchHasSelectorStore) = + .error err) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul → + EvmYul.Yul.exec (fuel + cases.length + 17) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + defaultBody]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) = + .error err ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul) := by + rcases + exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq_payable_generated_prefix + fuel selector switchId tag cases defaultBody body contract tx storage + initialEvents observableSlots nativeSwitchHasSelectorStore err nativeYul + reservedNames n0 next fn hSelector hFind hSelectorRange hTagsRange + hLower hPayable hguards hNoWrap hArgs with + ⟨bodyNative, bodyStart, hBodyLower, hEndpoint⟩ + refine ⟨bodyNative, bodyStart, hBodyLower, ?_⟩ + intro hBody hProject + rcases hEndpoint hBody hProject with ⟨hExec, hProject'⟩ + have hFuelEq : fuel + cases.length + 17 = + (fuel + cases.length + 16).succ := by + omega + rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] + exact ⟨exec_block_cons_error (fuel + cases.length + 16) _ [] _ _ err hExec, + hProject'⟩ -@[simp] theorem projectResult_yulHalt_success - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) +/-- Bridge-shape selector-hit error projection for a non-payable generated case + on the post-`__has_selector := 1` state, with generated case guards + discharged before the selected user body premise. -/ +theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq_nonpayable_generated_prefix + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (value : EvmYul.Yul.Ast.Literal) : - (projectResult tx initialStorage initialEvents - (.error (.YulHalt state value))).success = true := by - rfl + (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) + (nativeYul : YulResult) + (reservedNames : List String) (n0 next : Nat) + (fn : IRFunction) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (body, next)) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) ∧ + ((∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId + nativeSwitchHasSelectorStore) = + .error err) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul → + EvmYul.Yul.exec (fuel + cases.length + 18) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + defaultBody]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) = + .error err ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul) := by + rcases + exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq_nonpayable_generated_prefix + fuel selector switchId tag cases defaultBody body contract tx storage + initialEvents observableSlots nativeSwitchHasSelectorStore err nativeYul + reservedNames n0 next fn hSelector hFind hSelectorRange hTagsRange + hLower hNonPayable hguards hNoWrap hArgs with + ⟨bodyNative, bodyStart, hBodyLower, hEndpoint⟩ + refine ⟨bodyNative, bodyStart, hBodyLower, ?_⟩ + intro hBody hProject + rcases hEndpoint hBody hProject with ⟨hExec, hProject'⟩ + have hFuelEq : fuel + cases.length + 18 = + (fuel + cases.length + 17).succ := by + omega + rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] + exact ⟨exec_block_cons_error (fuel + cases.length + 17) _ [] _ _ err hExec, + hProject'⟩ -@[simp] theorem projectResult_yulHalt_returnValue - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (value : EvmYul.Yul.Ast.Literal) : - (projectResult tx initialStorage initialEvents - (.error (.YulHalt state value))).returnValue = - projectHaltReturn state value := by - rfl +/-- Selector-hit success projection for lowered native switches entered from + the standard empty-store switch state. This is the normal-result companion + to `exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq`. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hFresh : Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchMarkedPrefixStateForId contract tx + storage observableSlots switchId) = .ok final) + (hStmtPreserves : ∀ stmt, stmt ∈ body → + Backends.nativeSwitchMatchedTempName switchId ∉ Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) + (hProject : projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul := by + refine ⟨?_, hProject⟩ + exact exec_lowerNativeSwitchBlock_selector_find_hit_fresh_fuel + fuel selector switchId cases defaultBody tag body contract tx storage + observableSlots final hSelector hFind hSelectorRange hTagsRange hFresh + hBody hStmtPreserves + +/-- Store-parametric selector-hit success projection for lowered native + switches. The selected body may finish normally; callers provide the exact + projection of that final state at the native result boundary. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) + (store : EvmYul.Yul.VarStore) (final : EvmYul.Yul.State) + (nativeYul : YulResult) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hFresh : Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx + storage observableSlots switchId store) = .ok final) + (hStmtPreserves : ∀ stmt, stmt ∈ body → + Backends.nativeSwitchMatchedTempName switchId ∉ Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) + (hProject : projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (.Ok (initialState contract tx storage observableSlots).sharedState store) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul := by + refine ⟨?_, hProject⟩ + exact exec_lowerNativeSwitchBlock_selector_find_hit_fresh_store_fuel + fuel selector switchId tag cases defaultBody body contract tx storage + observableSlots store final hSelector hFind hSelectorRange hTagsRange + hFresh hBody hStmtPreserves + +/-- Bridge-shape selector-hit success projection on the post-`__has_selector` + state, deriving default-skip freshness and exposing the projected final + native result in one package. -/ +theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hFresh : Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx + storage observableSlots switchId nativeSwitchHasSelectorStore) = .ok final) + (hStmtPreserves : ∀ stmt, stmt ∈ body → + Backends.nativeSwitchMatchedTempName switchId ∉ Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) + (hProject : projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) : + EvmYul.Yul.exec (fuel + cases.length + 13) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) = .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul := by + rcases exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq + fuel selector switchId tag cases defaultBody body contract tx storage + initialEvents observableSlots nativeSwitchHasSelectorStore final nativeYul + hSelector hFind hSelectorRange hTagsRange hFresh hBody hStmtPreserves + hProject with + ⟨hEndpoint, hProject'⟩ + have hFuelEq : fuel + cases.length + 13 = (fuel + cases.length + 12).succ := by + omega + rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] + exact ⟨exec_block_cons_ok (fuel + cases.length + 12) _ [] _ _ final final + hEndpoint (by simp [EvmYul.Yul.exec]), hProject'⟩ + +/-- Bridge-shape selector-hit success projection on the post-`__has_selector` + state, with the selected-body matched-flag preservation supplied directly + as a block-level predicate. This is the same boundary as + `exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq`, + but avoids re-exposing per-statement preservation when callers already have + a `NativeBlockPreservesWord` proof for the selected body. -/ +theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_preserved + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchStoreMarkedPrefixStateForId contract tx + storage observableSlots switchId nativeSwitchHasSelectorStore) = .ok final) + (hPreservesMatched : ∀ pre suffix, + cases = pre ++ (tag, body) :: suffix → + NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) body (some contract)) + (hProject : projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) : + EvmYul.Yul.exec (fuel + cases.length + 13) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) = .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul := by + refine ⟨?_, hProject⟩ + have hEndpoint : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (some contract) + (nativeSwitchHasSelectorInitialState contract tx storage observableSlots) = + .ok final := by + exact exec_lowerNativeSwitchBlock_selector_find_hit_preserved_store_fuel + fuel selector switchId tag cases defaultBody body contract tx storage + observableSlots nativeSwitchHasSelectorStore final hSelector hFind + hSelectorRange hTagsRange hBody hPreservesMatched + have hFuelEq : fuel + cases.length + 13 = (fuel + cases.length + 12).succ := by + omega + rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] + exact exec_block_cons_ok (fuel + cases.length + 12) _ [] _ _ final final + hEndpoint (by simp [EvmYul.Yul.exec]) -/-- The exact native scalar-return primitive proof lifted through Verity's - projected native result boundary. This is the shape consumed by dispatcher - agreement: after native `mstore(0, value); return(0, 32)` halts, the - projected `YulResult.returnValue` is exactly the returned word. -/ -theorem primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue - (mstoreFuel returnFuel : Nat) - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) +/-- Bridge-shape selector-hit success projection for a payable generated case on + the post-`__has_selector := 1` state, with generated case guards discharged + before the selected user body premise. -/ +theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_payable_generated_prefix + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (sharedState : EvmYul.SharedState .Yul) - (store : EvmYul.Yul.VarStore) - (value : EvmYul.UInt256) - (hMemory : sharedState.memory = ByteArray.empty) : - ∃ haltState haltValue, - (do - let (state', values) ← - EvmYul.Yul.primCall (mstoreFuel + 1) (.Ok sharedState store) - EvmYul.Operation.MSTORE - [EvmYul.UInt256.ofNat 0, value] - match values with - | [] => - EvmYul.Yul.primCall (returnFuel + 1) state' - EvmYul.Operation.RETURN - [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx initialStorage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = - some value.toNat := by - rcases primCall_mstore0_then_return32_emptyMemory_projectHaltReturn - mstoreFuel returnFuel sharedState store value hMemory with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, hExec, ?_⟩ - simpa using hReturn + (observableSlots : List Nat) + (final : EvmYul.Yul.State) + (nativeYul : YulResult) + (reservedNames : List String) (n0 next : Nat) + (fn : IRFunction) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (body, next)) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) ∧ + ((∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + EvmYul.Yul.exec (fuel + cases.length + 17) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + defaultBody]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + rcases + exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq_payable_generated_prefix + fuel selector switchId tag cases defaultBody body contract tx storage + initialEvents observableSlots nativeSwitchHasSelectorStore final + nativeYul reservedNames n0 next fn hSelector hFind hSelectorRange + hTagsRange hLower hPayable hguards hNoWrap hArgs with + ⟨bodyNative, bodyStart, hBodyLower, hEndpoint⟩ + refine ⟨bodyNative, bodyStart, hBodyLower, ?_⟩ + intro hBody hPreserves hProject + rcases hEndpoint hBody hPreserves hProject with ⟨hExec, hProject'⟩ + have hFuelEq : fuel + cases.length + 17 = + (fuel + cases.length + 16).succ := by + omega + rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] + exact ⟨exec_block_cons_ok (fuel + cases.length + 16) _ [] _ _ + final final hExec (by simp [EvmYul.Yul.exec]), hProject'⟩ -/-- Exact projected result for the generated scalar-return primitive sequence. - Starting from empty native memory, `mstore(0, value); return(0, 32)` halts - through the actual EVMYulLean primitive relation and projects as a successful - one-word return containing exactly `value`. -/ -theorem primCall_mstore0_then_return32_emptyMemory_projectResult_eq - (mstoreFuel returnFuel : Nat) - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) +/-- Bridge-shape selector-hit success projection for a non-payable generated + case on the post-`__has_selector := 1` state, with generated case guards + discharged before the selected user body premise. -/ +theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_nonpayable_generated_prefix + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (contract : EvmYul.Yul.Ast.YulContract) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (sharedState : EvmYul.SharedState .Yul) - (store : EvmYul.Yul.VarStore) - (value : EvmYul.UInt256) - (hMemory : sharedState.memory = ByteArray.empty) : - ∃ haltState haltValue, - (do - let (state', values) ← - EvmYul.Yul.primCall (mstoreFuel + 1) (.Ok sharedState store) - EvmYul.Operation.MSTORE - [EvmYul.UInt256.ofNat 0, value] - match values with - | [] => - EvmYul.Yul.primCall (returnFuel + 1) state' - EvmYul.Operation.RETURN - [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - projectResult tx initialStorage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = - { success := true - returnValue := some value.toNat - finalStorage := projectStorageFromState tx haltState - finalMappings := - Compiler.Proofs.storageAsMappings (projectStorageFromState tx haltState) - events := initialEvents ++ projectLogsFromState haltState } := by + (observableSlots : List Nat) + (final : EvmYul.Yul.State) + (nativeYul : YulResult) + (reservedNames : List String) (n0 next : Nat) + (fn : IRFunction) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = + some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + (switchCaseBody fn) = .ok (body, next)) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (bodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart fn.body = + .ok (bodyNative, next) ∧ + ((∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots switchId + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + NativeBlockPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + EvmYul.Yul.exec (fuel + cases.length + 18) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + defaultBody]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by rcases - primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue - mstoreFuel returnFuel tx initialStorage initialEvents sharedState store value - hMemory with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, hExec, ?_⟩ - have hProjectReturn : - projectHaltReturn haltState haltValue = some value.toNat := by - simpa [projectResult] using hReturn - simp [projectResult, hProjectReturn] + exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq_nonpayable_generated_prefix + fuel selector switchId tag cases defaultBody body contract tx storage + initialEvents observableSlots nativeSwitchHasSelectorStore final + nativeYul reservedNames n0 next fn hSelector hFind hSelectorRange + hTagsRange hLower hNonPayable hguards hNoWrap hArgs with + ⟨bodyNative, bodyStart, hBodyLower, hEndpoint⟩ + refine ⟨bodyNative, bodyStart, hBodyLower, ?_⟩ + intro hBody hPreserves hProject + rcases hEndpoint hBody hPreserves hProject with ⟨hExec, hProject'⟩ + have hFuelEq : fuel + cases.length + 18 = + (fuel + cases.length + 17).succ := by + omega + rw [nativeSwitchInitialOkState_insert_hasSelector_eq, hFuelEq] + exact ⟨exec_block_cons_ok (fuel + cases.length + 17) _ [] _ _ + final final hExec (by simp [EvmYul.Yul.exec]), hProject'⟩ -/-- The native primitive sequence used by the generated SimpleStorage getter - body after dispatcher selection. -/ -def primCall_sload0_then_mstore0_return32_initialState - (sloadFuel mstoreFuel returnFuel : Nat) +/-- Contract-dispatcher boundary for a generated lowered selector-switch hit + whose selected body exits through an EVMYulLean error or halt channel. -/ +theorem contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq + (fuel selector switchId tag : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (dispatcher : EvmYul.Yul.Ast.Stmt) (functions : NativeFunctionMap) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) + (observableSlots : List Nat) (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hDispatcher : dispatcher = Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (hContract : contract = { dispatcher := .Block [dispatcher], functions := functions }) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) + (nativeSwitchMarkedPrefixStateForId contract tx storage + observableSlots switchId) = .error err) + (hProject : projectResult tx storage initialEvents (.error err) = nativeYul) : + contractDispatcherExecResult (Nat.succ (Nat.succ (fuel + cases.length + 12))) + contract (initialState contract tx storage observableSlots) = + .error err ∧ + projectResult tx storage initialEvents (.error err) = nativeYul := by + subst hDispatcher + subst hContract + let dispatcher' := + Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [dispatcher'], functions := functions } + rcases exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq + fuel selector switchId cases defaultBody tag body contract' tx storage + initialEvents observableSlots err nativeYul hSelector hFind hSelectorRange + hTagsRange hBody hProject with + ⟨hExec, hProject'⟩ + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (fuel + cases.length + 12) [dispatcher'] functions tx storage observableSlots] + exact + ⟨exec_block_cons_error (fuel + cases.length + 12) dispatcher' [] + (some contract') (nativeSwitchInitialOkState contract' tx storage observableSlots) + err hExec, + hProject'⟩ + +/-- Contract-dispatcher boundary for a generated lowered selector-switch hit + whose selected body finishes normally. -/ +theorem contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq + (fuel selector switchId tag : Nat) (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (defaultBody body : List EvmYul.Yul.Ast.Stmt) + (dispatcher : EvmYul.Yul.Ast.Stmt) (functions : NativeFunctionMap) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) + (observableSlots : List Nat) (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hDispatcher : dispatcher = Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody) + (hContract : contract = { dispatcher := .Block [dispatcher], functions := functions }) + (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = some (tag, body)) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : ∀ tag' body', (tag', body') ∈ cases → tag' < EvmYul.UInt256.size) + (hFresh : Backends.nativeSwitchTempsFreshForNativeBodies switchId cases defaultBody) + (hBody : ∀ pre suffix, cases = pre ++ (tag, body) :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body) + (some contract) (nativeSwitchMarkedPrefixStateForId contract tx storage + observableSlots switchId) = .ok final) + (hStmtPreserves : ∀ stmt, stmt ∈ body → + Backends.nativeSwitchMatchedTempName switchId ∉ Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord (Backends.nativeSwitchMatchedTempName switchId) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) + (hProject : projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) : + contractDispatcherExecResult (Nat.succ (Nat.succ (fuel + cases.length + 12))) + contract (initialState contract tx storage observableSlots) = .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul := by + subst hDispatcher + subst hContract + let dispatcher' := Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases defaultBody + let contract' : EvmYul.Yul.Ast.YulContract := { dispatcher := .Block [dispatcher'], functions := functions } + rcases exec_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq + fuel selector switchId tag cases defaultBody body contract' tx storage + initialEvents observableSlots final nativeYul hSelector hFind + hSelectorRange hTagsRange hFresh hBody hStmtPreserves hProject with + ⟨hExec, hProject'⟩ + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (fuel + cases.length + 12) [dispatcher'] functions tx storage observableSlots] + exact + ⟨exec_block_cons_ok (fuel + cases.length + 12) dispatcher' [] + (some contract') (nativeSwitchInitialOkState contract' tx storage observableSlots) + final final hExec (by simp [EvmYul.Yul.exec]), + hProject'⟩ + +/-- Guarded selector-miss execution for a fully lowered native switch block, + lifted through Verity's projected native result boundary. The generated + `revert(0, 0)` default both executes through the actual native step + relation and projects as a failed call with no return word and rolled-back + observable storage. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (observableSlots : List Nat) : - Except EvmYul.Yul.Exception - (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := do - let (state', values) ← - EvmYul.Yul.primCall (sloadFuel + 1) - (initialState contract tx storage observableSlots) - EvmYul.Operation.SLOAD [EvmYul.UInt256.ofNat 0] - match values with - | [value] => - (do - let (state'', values') ← - EvmYul.Yul.primCall (mstoreFuel + 1) state' - EvmYul.Operation.MSTORE [EvmYul.UInt256.ofNat 0, value] - match values' with - | [] => - EvmYul.Yul.primCall (returnFuel + 1) state'' - EvmYul.Operation.RETURN - [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) - | _ => .error EvmYul.Yul.Exception.InvalidArguments + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + [nativeRevertZeroZeroStmt]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + (projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert)).success = false ∧ + (projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert)).returnValue = none ∧ + (∀ slot, + (projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert)).finalStorage (IRStorageSlot.ofNat slot) = + storage (IRStorageSlot.ofNat slot)) := by + refine ⟨?_, ?_, ?_, ?_⟩ + · exact exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_fuel + fuel selector switchId cases contract tx storage observableSlots + hSelector hFind hSelectorRange hTagsRange + · simp + · simp + · intro slot + simp -/-- Store-parametric form of the native primitive sequence used by the - generated SimpleStorage getter body. The lowered dispatcher executes the - selected body after adding switch temporaries to the Yul `VarStore`, while - storage and memory effects are carried by the shared state. -/ -def primCall_sload0_then_mstore0_return32_initialState_withStore - (sloadFuel mstoreFuel returnFuel : Nat) +/-- Guarded selector-miss execution for a fully lowered native switch block, + with the projected revert result exposed as one exact `YulResult`. + +This generic package is the native dispatcher boundary needed by generated +selector-miss proofs: the lowered switch reaches EVMYulLean's `Revert`, and +Verity's projection rolls storage and events back to the call pre-state. -/ +theorem exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) : - Except EvmYul.Yul.Exception - (EvmYul.Yul.State × List EvmYul.Yul.Ast.Literal) := do - let (state', values) ← - EvmYul.Yul.primCall (sloadFuel + 1) - (.Ok (initialState contract tx storage observableSlots).sharedState store) - EvmYul.Operation.SLOAD [EvmYul.UInt256.ofNat 0] - match values with - | [value] => - (do - let (state'', values') ← - EvmYul.Yul.primCall (mstoreFuel + 1) state' - EvmYul.Operation.MSTORE [EvmYul.UInt256.ofNat 0, value] - match values' with - | [] => - EvmYul.Yul.primCall (returnFuel + 1) state'' - EvmYul.Operation.RETURN - [EvmYul.UInt256.ofNat 0, EvmYul.UInt256.ofNat 32] - | _ => .error EvmYul.Yul.Exception.InvalidArguments) - | _ => .error EvmYul.Yul.Exception.InvalidArguments + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + EvmYul.Yul.exec (fuel + cases.length + 12) + (Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + [nativeRevertZeroZeroStmt]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + { success := false + returnValue := none + finalStorage := storage + finalMappings := Compiler.Proofs.storageAsMappings storage + events := initialEvents } := by + rcases + exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult + fuel selector switchId cases contract tx storage initialEvents + observableSlots hSelector hFind hSelectorRange hTagsRange with + ⟨hExec, _hSuccess, _hReturn, _hStorage⟩ + exact ⟨hExec, by simp⟩ -/-- Native primitive execution of the generated `retrieve()` scalar-return core: - `sload(0)` reads the materialized slot-zero word, then `mstore(0, value); - return(0, 32)` returns that exact word through the projected native result. +/-- Contract-dispatcher boundary for a generated lowered selector-switch miss. -This composes the real EVMYulLean `SLOAD`, `MSTORE`, and `RETURN` primitive -relations for the SimpleStorage getter body, leaving only dispatcher selection -and oracle comparison around this selected-body path. -/ -theorem primCall_sload0_then_mstore0_return32_initialState_projectResult_returnValue - (sloadFuel mstoreFuel returnFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) +This lifts the generic `lowerNativeSwitchBlock` selector-miss theorem through +the actual native dispatcher execution wrapper used by the public EndToEnd +target. -/ +theorem contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq + (fuel selector switchId : Nat) + (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (functions : NativeFunctionMap) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (hSlot : 0 ∈ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - ∃ haltState haltValue, - primCall_sload0_then_mstore0_return32_initialState - sloadFuel mstoreFuel returnFuel contract tx storage observableSlots = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = - some (uint256ToNat (storage 0)) := by - unfold primCall_sload0_then_mstore0_return32_initialState - rw [primCall_sload_initialState_observableSlot_ok sloadFuel contract tx storage - observableSlots 0 hSlot hRange] - generalize hload : - EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 0) = loaded - cases loaded with - | mk stateAfterLoad _ => - let sharedAfterLoad : EvmYul.SharedState .Yul := - { (initialState contract tx storage observableSlots).toSharedState with - toState := stateAfterLoad } - have hMemory : sharedAfterLoad.memory = ByteArray.empty := by - simp [sharedAfterLoad, initialState, EvmYul.Yul.State.toSharedState, - YulState.initial, toSharedState] - rcases - primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue - mstoreFuel returnFuel tx storage initialEvents sharedAfterLoad ∅ - (storage 0) hMemory with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, ?_, ?_⟩ - · simpa [sharedAfterLoad] using hExec - · simpa [natToUInt256, EvmYul.UInt256.toNat, uint256ToNat] using hReturn + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hTagsRange : + ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : + let dispatcher := + Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr switchId cases + [nativeRevertZeroZeroStmt] + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [dispatcher], functions := functions } + contractDispatcherExecResult (Nat.succ (Nat.succ (fuel + cases.length + 12))) + contract (initialState contract tx storage observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + { success := false + returnValue := none + finalStorage := storage + finalMappings := Compiler.Proofs.storageAsMappings storage + events := initialEvents } := by + intro dispatcher contract + rcases + exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq + fuel selector switchId cases contract tx storage initialEvents + observableSlots hSelector hFind hSelectorRange hTagsRange with + ⟨hExec, hProject⟩ + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (fuel + cases.length + 12) [dispatcher] functions tx storage observableSlots] + exact + ⟨exec_block_cons_error (fuel + cases.length + 12) dispatcher [] (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) + EvmYul.Yul.Exception.Revert hExec, + hProject⟩ + +/-- Generic selector-miss native execution package for a no-fallback/no-receive + generated dispatcher. + +This opens the actual native lowering of `buildSwitch funcs none none`, links the +source function-table miss to the lowered lazy-switch miss, and lifts the result +through the real `contractDispatcherExecResult` wrapper. The fuel is still the +structural dispatcher fuel exposed by the current native switch lemmas; the +canonical theorem-facing fuel remains a separate monotonicity/size-bound step. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_projectResult_eq + (fuel selector : Nat) + (funcs : List IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun fn => fn.selector == selector) = none) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + { success := false + returnValue := none + finalStorage := storage + finalMappings := Compiler.Proofs.storageAsMappings storage + events := initialEvents } := by + obtain ⟨body1, reservedNames, n0, cases', midN, hInner, hLowerCases⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered funcs inner hLower + refine ⟨reservedNames, n0, cases', midN, ?_, ?_, ?_⟩ + · exact hLowerCases + · let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hLowerFind : + cases'.find? (fun entry => entry.1 == selector) = none := + lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function + reservedNames (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + selector funcs cases' hLowerCases hFind + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error + fuel selector (Backends.freshNativeSwitchId reservedNames n0) cases' + contract tx storage observableSlots hSelector hLowerFind hSelectorRange + hTagsRange + · simp -/-- Native primitive execution of the generated `retrieve()` scalar-return core - when slot zero was not materialized into the finite native storage map: - `sload(0)` returns the EVM zero word, and the following - `mstore(0, 0); return(0, 32)` projects as return value `0`. -/ -theorem primCall_sload0_then_mstore0_return32_initialState_omittedSlot_projectResult_returnValue - (sloadFuel mstoreFuel returnFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) +/-- Exact-total-fuel companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_projectResult_eq`. + +The theorem opens the generated dispatcher lowering first, exposes the lowered +case list, and then runs the dispatcher at any total fuel that covers the +structural selector-miss budget `cases'.length + 19`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_atFuel_projectResult_eq + (fuel' selector : Nat) + (funcs : List IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (hNotSlot : 0 ∉ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - ∃ haltState haltValue, - primCall_sload0_then_mstore0_return32_initialState - sloadFuel mstoreFuel returnFuel contract tx storage observableSlots = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = - some 0 := by - unfold primCall_sload0_then_mstore0_return32_initialState - rw [primCall_sload_initialState_omittedSlot_ok sloadFuel contract tx storage - observableSlots 0 hNotSlot hRange (by norm_num [EvmYul.UInt256.size])] - generalize hload : - EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 0) = loaded - cases loaded with - | mk stateAfterLoad _ => - let sharedAfterLoad : EvmYul.SharedState .Yul := - { (initialState contract tx storage observableSlots).toSharedState with - toState := stateAfterLoad } - have hMemory : sharedAfterLoad.memory = ByteArray.empty := by - simp [sharedAfterLoad, initialState, EvmYul.Yul.State.toSharedState, - YulState.initial, toSharedState] - rcases - primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue - mstoreFuel returnFuel tx storage initialEvents sharedAfterLoad ∅ - (natToUInt256 0) hMemory with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, ?_, ?_⟩ - · simpa [sharedAfterLoad] using hExec - · simpa [natToUInt256, EvmYul.UInt256.toNat, uint256ToNat] using hReturn + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun fn => fn.selector == selector) = none) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + (cases'.length + 19 ≤ fuel' → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + { success := false + returnValue := none + finalStorage := storage + finalMappings := Compiler.Proofs.storageAsMappings storage + events := initialEvents }) := by + obtain ⟨body1, reservedNames, n0, cases', midN, hInner, hLowerCases⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered funcs inner hLower + refine ⟨reservedNames, n0, cases', midN, ?_, ?_⟩ + · exact hLowerCases + · intro hFuel + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hLowerFind : + cases'.find? (fun entry => entry.1 == selector) = none := + lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function + reservedNames (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + selector funcs cases' hLowerCases hFind + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + constructor + · rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error + fuel selector (Backends.freshNativeSwitchId reservedNames n0) cases' + contract tx storage observableSlots hSelector hLowerFind hSelectorRange + hTagsRange + · simp -/-- Native primitive execution of the generated `retrieve()` scalar-return core, - with the slot-zero materialization split discharged internally. +/-- Generic selector-hit native execution package for a no-fallback/no-receive +generated dispatcher when the selected native body exits through an error/halt +channel. -If slot zero was materialized as observable native storage, the getter returns - the projected Verity storage word. If it was omitted from materialization, - EVMYulLean's `SLOAD` default-zero behavior is exposed as return value zero. - This theorem removes the caller-side `0 ∈ observableSlots`/`0 ∉ - observableSlots` premise split from the selected-body dispatcher proof. -/ -theorem primCall_sload0_then_mstore0_return32_initialState_projectResult_returnValue_materialized - (sloadFuel mstoreFuel returnFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) +The theorem opens `buildSwitch` lowering, exposes the selected lowered body, and +packages the remaining body-execution premise at the post-selector-match state. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq + (fuel selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - ∃ haltState haltValue, - primCall_sload0_then_mstore0_return32_initialState - sloadFuel mstoreFuel returnFuel contract tx storage observableSlots = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = - if 0 ∈ observableSlots then - some (uint256ToNat (storage 0)) - else - some 0 := by - by_cases hSlot : 0 ∈ observableSlots - · rcases - primCall_sload0_then_mstore0_return32_initialState_projectResult_returnValue - sloadFuel mstoreFuel returnFuel contract tx storage initialEvents - observableSlots hSlot hRange with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, hExec, ?_⟩ - rw [if_pos hSlot] - simpa using hReturn - · rcases - primCall_sload0_then_mstore0_return32_initialState_omittedSlot_projectResult_returnValue - sloadFuel mstoreFuel returnFuel contract tx storage initialEvents - observableSlots hSlot hRange with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, hExec, ?_⟩ - rw [if_neg hSlot] - simpa using hReturn - -/-- Native primitive execution of the generated `retrieve()` scalar-return core - from an arbitrary local store when slot zero is materialized. -/ -theorem primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_returnValue - (sloadFuel mstoreFuel returnFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) + (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .error err) → + projectResult tx storage initialEvents (.error err) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + .error err ∧ + projectResult tx storage initialEvents (.error err) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, ?_, ?_, ?_⟩ + · exact hCase + · exact hBodyLower + · intro hBody hProject + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + fuel selector (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots err nativeYul hSelector hCase hSelectorRange hTagsRange + hBody hProject + +/-- Structural dispatcher/prologue peel for no-fallback/no-receive generated + dispatchers after the selector availability guard succeeds. This isolates + the common `__has_selector` setup and lazy native switch entry shape. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel : Nat) + (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body1 inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (hInner : + inner = + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) : + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + intro contract + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + +/-- Generated-prefix variant of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq` +for payable functions. + +The public selected-body premise is over the lowered user body `fn.body`, not +the whole generated `switchCaseBody fn`; this theorem discharges the generated +comment no-op and calldata-size guard before applying the existing dispatcher +selector-hit wrapper at the correspondingly larger structural fuel. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_payable_generated_prefix_projectResult_eq + (fuel selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .error err) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 23) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error err ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul) := by + obtain ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq + (fuel + 4) selector funcs fn inner functions (YulTransaction.ofIR tx) + storage initialEvents observableSlots err nativeYul hLower hSelector + hFind (by simpa [YulTransaction.ofIR_args] using hNoWrap) + hSelectorRange hFunctionSelectorsRange + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + reservedNames bodyStart fn body' bodyEnd hPayable hBodyLower with + ⟨guardBody, bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + refine ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hUserBody hProject + have hWholeBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 4) + 1) + suffix.length + 7) + (.Block body') (some + ({ dispatcher := .Block [.Block inner], functions := functions } : + EvmYul.Yul.Ast.YulContract)) + (nativeSwitchStoreMarkedPrefixStateForId + ({ dispatcher := .Block [.Block inner], functions := functions } : + EvmYul.Yul.Ast.YulContract) + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .error err := by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := exec_switchCaseBody_payable_prefix_eq + (fuel + suffix.length + 1) guardBody bodyNative + ({ dispatcher := .Block [.Block inner], functions := functions } : + EvmYul.Yul.Ast.YulContract) + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + (by simp; omega) + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + hPrefix.trans (hUserBody pre suffix hCases) + have hResult := hCont hWholeBody hProject + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hResult + +/-- Generated-prefix variant of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq` +for non-payable functions. + +The public selected-body premise is over the lowered user body `fn.body`; this +theorem discharges the generated comment no-op, callvalue guard, and +calldata-size guard before applying the existing dispatcher selector-hit +wrapper at the correspondingly larger structural fuel. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_nonpayable_generated_prefix_projectResult_eq + (fuel selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .error err) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 24) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error err ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error err) = nativeYul) := by + obtain ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq + (fuel + 5) selector funcs fn inner functions (YulTransaction.ofIR tx) + storage initialEvents observableSlots err nativeYul hLower hSelector + hFind (by simpa [YulTransaction.ofIR_args] using hNoWrap) + hSelectorRange hFunctionSelectorsRange + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨callvalueGuardBody, calldataGuardBody, bodyNative, userBodyStart, + hBodyShape, hUserBodyLower⟩ + refine ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hUserBody hProject + have hWholeBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 5) + 1) + suffix.length + 7) + (.Block body') (some + ({ dispatcher := .Block [.Block inner], functions := functions } : + EvmYul.Yul.Ast.YulContract)) + (nativeSwitchStoreMarkedPrefixStateForId + ({ dispatcher := .Block [.Block inner], functions := functions } : + EvmYul.Yul.Ast.YulContract) + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .error err := by + intro pre suffix hCases + rw [hBodyShape] + have hPrefix := exec_switchCaseBody_nonpayable_prefix_eq + (fuel + suffix.length + 1) callvalueGuardBody calldataGuardBody + bodyNative + ({ dispatcher := .Block [.Block inner], functions := functions } : + EvmYul.Yul.Ast.YulContract) + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable fn tx hguards + hNonPayable) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + (by simp; omega) + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using + hPrefix.trans (hUserBody pre suffix hCases) + have hResult := hCont hWholeBody hProject + simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hResult + +set_option linter.unusedVariables false in +/-- Non-payable selector-hit value-guard failure for a generated dispatcher. + +This closes the generated `callvalue()` revert path directly: when the selected +function is non-payable and `msgValue` is nonzero modulo the EVM word modulus, +the selected switch-case prefix reverts before the calldata guard or user body. +-/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_callvalue_revert_projectResult_eq + (fuel selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hNonzero : tx.msgValue % evmModulus ≠ 0) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + contractDispatcherExecResult (fuel + cases'.length + 24) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) := by + obtain ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq + (fuel + 5) selector funcs fn inner functions (YulTransaction.ofIR tx) + storage initialEvents observableSlots EvmYul.Yul.Exception.Revert + (projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) + hLower hSelector hFind + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + hSelectorRange hFunctionSelectorsRange + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hWholeBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 5) + 1) + suffix.length + 7) + (.Block body') (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = + .error EvmYul.Yul.Exception.Revert := by + intro pre suffix _hCases + rw [hBodyShape] + have hExec := + exec_switchCaseBody_nonpayable_callvalue_revert_fuel + (fuel + suffix.length + 1) + [nativeRevertZeroZeroStmt] bodyNative contract (YulTransaction.ofIR tx) storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR] using hNonzero) + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hExec + have hResult := hCont hWholeBody rfl + refine ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hResult + +set_option linter.unusedVariables false in +/-- Exact-total-fuel companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_callvalue_revert_projectResult_eq`. +-/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_callvalue_revert_atFuel_projectResult_eq + (fuel' selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hNonzero : tx.msgValue % evmModulus ≠ 0) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 24 ≤ fuel' → + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, + hUserBodyLower, ?_⟩ + intro hFuel + let fuel := fuel' - (cases'.length + 24) + have hFuelShape : fuel' = fuel + cases'.length + 24 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 5) reservedNames n0 cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 18) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hDispatcherFuel : + fuel + cases'.length + 24 = + (fuel + 5) + cases'.length + 19 := by omega + have hSwitchFuel : + fuel + cases'.length + 18 = + (fuel + 5) + cases'.length + 13 := by omega + rw [hDispatcherFuel, hSwitchFuel] + simpa [contract] using hPeel + rw [hPeel'] + have hBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 5) + 1) + suffix.length + 7) + (.Block body') (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = + .error EvmYul.Yul.Exception.Revert := by + intro pre suffix _hCases + rw [hBodyShape] + have hExec := + exec_switchCaseBody_nonpayable_callvalue_revert_fuel + (fuel + suffix.length + 1) + [nativeRevertZeroZeroStmt] bodyNative contract (YulTransaction.ofIR tx) + storage observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR] using hNonzero) + rw [show (((fuel + 5) + 1) + suffix.length + 7) = + (fuel + suffix.length + 1) + 12 by omega] + exact hExec + have hSwitch := + exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + (fuel + 5) selector (Backends.freshNativeSwitchId reservedNames n0) + selector cases' [nativeRevertZeroZeroStmt] body' contract + (YulTransaction.ofIR tx) storage initialEvents observableSlots + EvmYul.Yul.Exception.Revert + (projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) + hSelector hCase hSelectorRange hTagsRange hBody rfl + rw [show fuel + cases'.length + 18 = + (fuel + 5) + cases'.length + 13 by omega] + simpa [Compiler.Proofs.YulGeneration.selectorExpr] using hSwitch + +set_option linter.unusedVariables false in +/-- Payable selector-hit calldata guard failure for a generated dispatcher. + +When the selected function is payable but the ABI calldata is too short for +its parameter count, the selected switch-case prefix reverts before the user +body executes. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_payable_args_short_revert_projectResult_eq + (fuel selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + contractDispatcherExecResult (fuel + cases'.length + 23) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) := by + obtain ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq + (fuel + 4) selector funcs fn inner functions (YulTransaction.ofIR tx) + storage initialEvents observableSlots EvmYul.Yul.Exception.Revert + (projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) + hLower hSelector hFind + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + hSelectorRange hFunctionSelectorsRange + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_revert_eq + reservedNames bodyStart fn body' bodyEnd hPayable hBodyLower with + ⟨bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hCalldataLt : + 4 + (YulTransaction.ofIR tx).args.length * 32 < + 4 + fn.params.length * 32 := by + have hArgLt : tx.args.length < fn.params.length := by omega + simpa [YulTransaction.ofIR_args] using + (by omega : + 4 + tx.args.length * 32 < 4 + fn.params.length * 32) + have hWholeBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 4) + 1) + suffix.length + 7) + (.Block body') (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = + .error EvmYul.Yul.Exception.Revert := by + intro pre suffix _hCases + rw [hBodyShape] + have hExec := + exec_switchCaseBody_payable_calldata_revert_fuel + (fuel + suffix.length + 1) bodyNative contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + hCalldataLt + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hExec + have hResult := hCont hWholeBody rfl + refine ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hResult + +set_option linter.unusedVariables false in +/-- Non-payable selector-hit calldata guard failure for a generated dispatcher +after the zero-callvalue guard skips. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_args_short_revert_projectResult_eq + (fuel selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hZero : tx.msgValue % evmModulus = 0) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + contractDispatcherExecResult (fuel + cases'.length + 24) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) := by + obtain ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, + hCase, hBodyLower, hCont⟩ := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq + (fuel + 5) selector funcs fn inner functions (YulTransaction.ofIR tx) + storage initialEvents observableSlots EvmYul.Yul.Exception.Revert + (projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) + hLower hSelector hFind + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + hSelectorRange hFunctionSelectorsRange + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hCalldataLt : + 4 + (YulTransaction.ofIR tx).args.length * 32 < + 4 + fn.params.length * 32 := by + have hArgLt : tx.args.length < fn.params.length := by omega + simpa [YulTransaction.ofIR_args] using + (by omega : + 4 + tx.args.length * 32 < 4 + fn.params.length * 32) + have hWholeBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 5) + 1) + suffix.length + 7) + (.Block body') (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = + .error EvmYul.Yul.Exception.Revert := by + intro pre suffix _hCases + rw [hBodyShape] + have hExec := + exec_switchCaseBody_nonpayable_calldata_revert_fuel + (fuel + suffix.length + 1) bodyNative contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR] using hZero) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + hCalldataLt + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hExec + have hResult := hCont hWholeBody rfl + refine ⟨reservedNames, n0, cases', body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hCase, hBodyLower, hUserBodyLower, ?_⟩ + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hResult + +set_option linter.unusedVariables false in +/-- Exact-total-fuel companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_payable_args_short_revert_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_payable_args_short_revert_atFuel_projectResult_eq + (fuel' selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 23 ≤ fuel' → + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_revert_eq + reservedNames bodyStart fn body' bodyEnd hPayable hBodyLower with + ⟨bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hCalldataLt : + 4 + (YulTransaction.ofIR tx).args.length * 32 < + 4 + fn.params.length * 32 := by + have hArgLt : tx.args.length < fn.params.length := by omega + simpa [YulTransaction.ofIR_args] using + (by omega : + 4 + tx.args.length * 32 < 4 + fn.params.length * 32) + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, + hUserBodyLower, ?_⟩ + intro hFuel + let fuel := fuel' - (cases'.length + 23) + have hFuelShape : fuel' = fuel + cases'.length + 23 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 4) reservedNames n0 cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hDispatcherFuel : + fuel + cases'.length + 23 = + (fuel + 4) + cases'.length + 19 := by omega + have hSwitchFuel : + fuel + cases'.length + 17 = + (fuel + 4) + cases'.length + 13 := by omega + rw [hDispatcherFuel, hSwitchFuel] + simpa [contract] using hPeel + rw [hPeel'] + have hBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 4) + 1) + suffix.length + 7) + (.Block body') (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = + .error EvmYul.Yul.Exception.Revert := by + intro pre suffix _hCases + rw [hBodyShape] + have hExec := + exec_switchCaseBody_payable_calldata_revert_fuel + (fuel + suffix.length + 1) bodyNative contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + hCalldataLt + rw [show (((fuel + 4) + 1) + suffix.length + 7) = + (fuel + suffix.length + 1) + 11 by omega] + exact hExec + have hSwitch := + exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + (fuel + 4) selector (Backends.freshNativeSwitchId reservedNames n0) + selector cases' [nativeRevertZeroZeroStmt] body' contract + (YulTransaction.ofIR tx) storage initialEvents observableSlots + EvmYul.Yul.Exception.Revert + (projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) + hSelector hCase hSelectorRange hTagsRange hBody rfl + rw [show fuel + cases'.length + 17 = + (fuel + 4) + cases'.length + 13 by omega] + simpa [Compiler.Proofs.YulGeneration.selectorExpr] using hSwitch + +set_option linter.unusedVariables false in +/-- Exact-total-fuel companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_args_short_revert_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_args_short_revert_atFuel_projectResult_eq + (fuel' selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hZero : tx.msgValue % evmModulus = 0) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 24 ≤ fuel' → + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hCalldataLt : + 4 + (YulTransaction.ofIR tx).args.length * 32 < + 4 + fn.params.length * 32 := by + have hArgLt : tx.args.length < fn.params.length := by omega + simpa [YulTransaction.ofIR_args] using + (by omega : + 4 + tx.args.length * 32 < 4 + fn.params.length * 32) + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, + hUserBodyLower, ?_⟩ + intro hFuel + let fuel := fuel' - (cases'.length + 24) + have hFuelShape : fuel' = fuel + cases'.length + 24 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 5) reservedNames n0 cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 18) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hDispatcherFuel : + fuel + cases'.length + 24 = + (fuel + 5) + cases'.length + 19 := by omega + have hSwitchFuel : + fuel + cases'.length + 18 = + (fuel + 5) + cases'.length + 13 := by omega + rw [hDispatcherFuel, hSwitchFuel] + simpa [contract] using hPeel + rw [hPeel'] + have hBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 5) + 1) + suffix.length + 7) + (.Block body') (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = + .error EvmYul.Yul.Exception.Revert := by + intro pre suffix _hCases + rw [hBodyShape] + have hExec := + exec_switchCaseBody_nonpayable_calldata_revert_fuel + (fuel + suffix.length + 1) bodyNative contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR] using hZero) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + hCalldataLt + rw [show (((fuel + 5) + 1) + suffix.length + 7) = + (fuel + suffix.length + 1) + 12 by omega] + exact hExec + have hSwitch := + exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + (fuel + 5) selector (Backends.freshNativeSwitchId reservedNames n0) + selector cases' [nativeRevertZeroZeroStmt] body' contract + (YulTransaction.ofIR tx) storage initialEvents observableSlots + EvmYul.Yul.Exception.Revert + (projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) + hSelector hCase hSelectorRange hTagsRange hBody rfl + rw [show fuel + cases'.length + 18 = + (fuel + 5) + cases'.length + 13 by omega] + simpa [Compiler.Proofs.YulGeneration.selectorExpr] using hSwitch + +set_option linter.unusedVariables false in +/-- Exact-total-fuel reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_callvalue_revert_atFuel_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_callvalue_revert_withSwitchIds_atFuel_projectResult_eq + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hNonzero : tx.msgValue % evmModulus ≠ 0) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 24 ≤ fuel' → + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel + let fuel := fuel' - (cases'.length + 24) + have hFuelShape : fuel' = fuel + cases'.length + 24 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 5) reservedNames switchStart cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 18) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hDispatcherFuel : + fuel + cases'.length + 24 = + (fuel + 5) + cases'.length + 19 := by omega + have hSwitchFuel : + fuel + cases'.length + 18 = + (fuel + 5) + cases'.length + 13 := by omega + rw [hDispatcherFuel, hSwitchFuel] + simpa [contract] using hPeel + rw [hPeel'] + have hBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 5) + 1) + suffix.length + 7) + (.Block body') (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = + .error EvmYul.Yul.Exception.Revert := by + intro pre suffix _hCases + rw [hBodyShape] + have hExec := + exec_switchCaseBody_nonpayable_callvalue_revert_fuel + (fuel + suffix.length + 1) + [nativeRevertZeroZeroStmt] bodyNative contract (YulTransaction.ofIR tx) + storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR] using hNonzero) + rw [show (((fuel + 5) + 1) + suffix.length + 7) = + (fuel + suffix.length + 1) + 12 by omega] + exact hExec + have hSwitch := + exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + (fuel + 5) selector (Backends.freshNativeSwitchId reservedNames switchStart) + selector cases' [nativeRevertZeroZeroStmt] body' contract + (YulTransaction.ofIR tx) storage initialEvents observableSlots + EvmYul.Yul.Exception.Revert + (projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) + hSelector hCase hSelectorRange hTagsRange hBody rfl + rw [show fuel + cases'.length + 18 = + (fuel + 5) + cases'.length + 13 by omega] + simpa [Compiler.Proofs.YulGeneration.selectorExpr] using hSwitch + +set_option linter.unusedVariables false in +/-- Exact-total-fuel reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_payable_args_short_revert_atFuel_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_payable_args_short_revert_withSwitchIds_atFuel_projectResult_eq + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 23 ≤ fuel' → + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_revert_eq + reservedNames bodyStart fn body' bodyEnd hPayable hBodyLower with + ⟨bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hCalldataLt : + 4 + (YulTransaction.ofIR tx).args.length * 32 < + 4 + fn.params.length * 32 := by + have hArgLt : tx.args.length < fn.params.length := by omega + simpa [YulTransaction.ofIR_args] using + (by omega : + 4 + tx.args.length * 32 < 4 + fn.params.length * 32) + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel + let fuel := fuel' - (cases'.length + 23) + have hFuelShape : fuel' = fuel + cases'.length + 23 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 4) reservedNames switchStart cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hDispatcherFuel : + fuel + cases'.length + 23 = + (fuel + 4) + cases'.length + 19 := by omega + have hSwitchFuel : + fuel + cases'.length + 17 = + (fuel + 4) + cases'.length + 13 := by omega + rw [hDispatcherFuel, hSwitchFuel] + simpa [contract] using hPeel + rw [hPeel'] + have hBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 4) + 1) + suffix.length + 7) + (.Block body') (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = + .error EvmYul.Yul.Exception.Revert := by + intro pre suffix _hCases + rw [hBodyShape] + have hExec := + exec_switchCaseBody_payable_calldata_revert_fuel + (fuel + suffix.length + 1) bodyNative contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + hCalldataLt + rw [show (((fuel + 4) + 1) + suffix.length + 7) = + (fuel + suffix.length + 1) + 11 by omega] + exact hExec + have hSwitch := + exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + (fuel + 4) selector (Backends.freshNativeSwitchId reservedNames switchStart) + selector cases' [nativeRevertZeroZeroStmt] body' contract + (YulTransaction.ofIR tx) storage initialEvents observableSlots + EvmYul.Yul.Exception.Revert + (projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) + hSelector hCase hSelectorRange hTagsRange hBody rfl + rw [show fuel + cases'.length + 17 = + (fuel + 4) + cases'.length + 13 by omega] + simpa [Compiler.Proofs.YulGeneration.selectorExpr] using hSwitch + +set_option linter.unusedVariables false in +/-- Exact-total-fuel reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_args_short_revert_atFuel_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_args_short_revert_withSwitchIds_atFuel_projectResult_eq + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (hSlot : 0 ∈ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - ∃ haltState haltValue, - primCall_sload0_then_mstore0_return32_initialState_withStore - sloadFuel mstoreFuel returnFuel contract tx storage observableSlots - store = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = - some (uint256ToNat (storage 0)) := by - unfold primCall_sload0_then_mstore0_return32_initialState_withStore - rw [primCall_sload_initialState_observableSlot_ok_withStore sloadFuel - contract tx storage observableSlots store 0 hSlot hRange] - generalize hload : - EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 0) = loaded - cases loaded with - | mk stateAfterLoad _ => - let initialWithStore : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - let sharedAfterLoad : EvmYul.SharedState .Yul := - { initialWithStore.toSharedState with toState := stateAfterLoad } - have hMemory : sharedAfterLoad.memory = ByteArray.empty := by - change initialWithStore.toSharedState.memory = ByteArray.empty - simp [initialWithStore, initialState, EvmYul.Yul.State.toSharedState, - EvmYul.Yul.State.sharedState, YulState.initial, toSharedState] - rcases - primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue - mstoreFuel returnFuel tx storage initialEvents sharedAfterLoad store - (storage 0) hMemory with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, ?_, ?_⟩ - · simpa [sharedAfterLoad, initialWithStore] using hExec - · simpa [natToUInt256, EvmYul.UInt256.toNat, uint256ToNat] using hReturn - -/-- Native primitive execution of the generated `retrieve()` scalar-return core - from an arbitrary local store when slot zero is omitted. -/ -theorem primCall_sload0_then_mstore0_return32_initialState_withStore_omittedSlot_projectResult_returnValue - (sloadFuel mstoreFuel returnFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hZero : tx.msgValue % evmModulus = 0) + (hArgsShort : ¬ fn.params.length ≤ tx.args.length) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 24 ≤ fuel' → + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + rcases lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq + reservedNames bodyStart fn body' bodyEnd hNonPayable hBodyLower with + ⟨bodyNative, userBodyStart, hBodyShape, hUserBodyLower⟩ + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hCalldataLt : + 4 + (YulTransaction.ofIR tx).args.length * 32 < + 4 + fn.params.length * 32 := by + have hArgLt : tx.args.length < fn.params.length := by omega + simpa [YulTransaction.ofIR_args] using + (by omega : + 4 + tx.args.length * 32 < 4 + fn.params.length * 32) + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel + let fuel := fuel' - (cases'.length + 24) + have hFuelShape : fuel' = fuel + cases'.length + 24 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 5) reservedNames switchStart cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 18) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hDispatcherFuel : + fuel + cases'.length + 24 = + (fuel + 5) + cases'.length + 19 := by omega + have hSwitchFuel : + fuel + cases'.length + 18 = + (fuel + 5) + cases'.length + 13 := by omega + rw [hDispatcherFuel, hSwitchFuel] + simpa [contract] using hPeel + rw [hPeel'] + have hBody : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel + 5) + 1) + suffix.length + 7) + (.Block body') (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = + .error EvmYul.Yul.Exception.Revert := by + intro pre suffix _hCases + rw [hBodyShape] + have hExec := + exec_switchCaseBody_nonpayable_calldata_revert_fuel + (fuel + suffix.length + 1) bodyNative contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore (4 + fn.params.length * 32) + (by simpa [YulTransaction.ofIR] using hZero) + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + (DispatchGuardsSafe_calldata_threshold_lt fn tx hguards) + hCalldataLt + rw [show (((fuel + 5) + 1) + suffix.length + 7) = + (fuel + suffix.length + 1) + 12 by omega] + exact hExec + have hSwitch := + exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + (fuel + 5) selector (Backends.freshNativeSwitchId reservedNames switchStart) + selector cases' [nativeRevertZeroZeroStmt] body' contract + (YulTransaction.ofIR tx) storage initialEvents observableSlots + EvmYul.Yul.Exception.Revert + (projectResult (YulTransaction.ofIR tx) storage initialEvents + (.error EvmYul.Yul.Exception.Revert)) + hSelector hCase hSelectorRange hTagsRange hBody rfl + rw [show fuel + cases'.length + 18 = + (fuel + 5) + cases'.length + 13 by omega] + simpa [Compiler.Proofs.YulGeneration.selectorExpr] using hSwitch + +/-- Generated-prefix success variant for payable selector hits. The public + selected-body premises are over the lowered user body `fn.body`, not over + the generated `switchCaseBody fn` wrapper. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_generated_prefix_projectResult_eq + (fuel selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (hNotSlot : 0 ∉ observableSlots) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - ∃ haltState haltValue, - primCall_sload0_then_mstore0_return32_initialState_withStore - sloadFuel mstoreFuel returnFuel contract tx storage observableSlots - store = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = - some 0 := by - unfold primCall_sload0_then_mstore0_return32_initialState_withStore - rw [primCall_sload_initialState_omittedSlot_ok_withStore sloadFuel - contract tx storage observableSlots store 0 hNotSlot hRange - (by norm_num [EvmYul.UInt256.size])] - generalize hload : - EvmYul.State.sload - (initialState contract tx storage observableSlots).toState - (natToUInt256 0) = loaded - cases loaded with - | mk stateAfterLoad _ => - let initialWithStore : EvmYul.Yul.State := - .Ok (initialState contract tx storage observableSlots).sharedState store - let sharedAfterLoad : EvmYul.SharedState .Yul := - { initialWithStore.toSharedState with toState := stateAfterLoad } - have hMemory : sharedAfterLoad.memory = ByteArray.empty := by - change initialWithStore.toSharedState.memory = ByteArray.empty - simp [initialWithStore, initialState, EvmYul.Yul.State.toSharedState, - EvmYul.Yul.State.sharedState, YulState.initial, toSharedState] - rcases - primCall_mstore0_then_return32_emptyMemory_projectResult_returnValue - mstoreFuel returnFuel tx storage initialEvents sharedAfterLoad store - (natToUInt256 0) hMemory with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, ?_, ?_⟩ - · simpa [sharedAfterLoad, initialWithStore] using hExec - · simpa [natToUInt256, EvmYul.UInt256.toNat, uint256ToNat] using hReturn - -/-- Native primitive execution of the generated `retrieve()` scalar-return core - from an arbitrary local store, with materialized/omitted slot zero handled - internally. -/ -theorem primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_returnValue_materialized - (sloadFuel mstoreFuel returnFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 23) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange _ hFn + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 4) reservedNames n0 cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult (fuel + cases'.length + 23) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hPeel + have hBlock := + exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_payable_generated_prefix + fuel selector (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage + initialEvents observableSlots final nativeYul reservedNames bodyStart + bodyEnd fn hSelector hCase hSelectorRange hTagsRange hBodyLower + hPayable hguards hNoWrap hArgs + rcases hBlock with ⟨bodyNative, userBodyStart, hUserBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, + bodyEnd, userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, + ?_⟩ + intro hUserBody hPreservesUser hProject + rw [hPeel'] + have hResult := hCont hUserBody hPreservesUser hProject + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hResult + +/-- Generated-prefix success variant for non-payable selector hits. The public + selected-body premises are over the lowered user body `fn.body`, not over + the generated `switchCaseBody fn` wrapper. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_generated_prefix_projectResult_eq + (fuel selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - ∃ haltState haltValue, - primCall_sload0_then_mstore0_return32_initialState_withStore - sloadFuel mstoreFuel returnFuel contract tx storage observableSlots - store = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - (projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue))).returnValue = - if 0 ∈ observableSlots then - some (uint256ToNat (storage 0)) - else - some 0 := by - by_cases hSlot : 0 ∈ observableSlots - · rcases - primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_returnValue - sloadFuel mstoreFuel returnFuel contract tx storage initialEvents - observableSlots store hSlot hRange with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, hExec, ?_⟩ - rw [if_pos hSlot] - simpa using hReturn - · rcases - primCall_sload0_then_mstore0_return32_initialState_withStore_omittedSlot_projectResult_returnValue - sloadFuel mstoreFuel returnFuel contract tx storage initialEvents - observableSlots store hSlot hRange with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, hExec, ?_⟩ - rw [if_neg hSlot] - simpa using hReturn - -/-- Exact projected result for the generated `retrieve()` scalar-return core - from an arbitrary dispatcher local store. This strengthens - `primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_returnValue_materialized` - from a return-value field fact to the full `YulResult` shape produced by the - native `SLOAD; MSTORE; RETURN` halt. -/ -theorem primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_eq_materialized - (sloadFuel mstoreFuel returnFuel : Nat) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 24) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange _ hFn + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 5) reservedNames n0 cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult (fuel + cases'.length + 24) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 18) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hPeel + have hBlock := + exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_nonpayable_generated_prefix + fuel selector (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage + initialEvents observableSlots final nativeYul reservedNames bodyStart + bodyEnd fn hSelector hCase hSelectorRange hTagsRange hBodyLower + hNonPayable hguards hNoWrap hArgs + rcases hBlock with ⟨bodyNative, userBodyStart, hUserBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hUserBody hPreservesUser hProject + rw [hPeel'] + have hResult := hCont hUserBody hPreservesUser hProject + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hResult + +/-- Reserved-context generated-prefix success variant for payable selector hits. + The selected-body premises are over the lowered user body `fn.body`, not + over the generated `switchCaseBody fn` wrapper. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_withSwitchIds_generated_prefix_projectResult_eq + (fuel selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) + (tx : IRTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) - (store : EvmYul.Yul.VarStore) - (hRange : ∀ s ∈ observableSlots, s < EvmYul.UInt256.size) : - ∃ haltState haltValue, - primCall_sload0_then_mstore0_return32_initialState_withStore - sloadFuel mstoreFuel returnFuel contract tx storage observableSlots - store = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue) ∧ - projectResult tx storage initialEvents - (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = - { success := true - returnValue := - if 0 ∈ observableSlots then - some (uint256ToNat (storage 0)) - else - some 0 - finalStorage := projectStorageFromState tx haltState - finalMappings := - Compiler.Proofs.storageAsMappings (projectStorageFromState tx haltState) - events := initialEvents ++ projectLogsFromState haltState } := by - rcases - primCall_sload0_then_mstore0_return32_initialState_withStore_projectResult_returnValue_materialized - sloadFuel mstoreFuel returnFuel contract tx storage initialEvents - observableSlots store hRange with - ⟨haltState, haltValue, hExec, hReturn⟩ - refine ⟨haltState, haltValue, hExec, ?_⟩ - have hProjectReturn : - projectHaltReturn haltState haltValue = - if 0 ∈ observableSlots then - some (uint256ToNat (storage 0)) - else - some 0 := by - simpa [projectResult] using hReturn - simp [projectResult, hProjectReturn] - -@[simp] theorem projectResult_yulHalt_finalMappings - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 23) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange _ hFn + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 4) reservedNames switchStart cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult (fuel + cases'.length + 23) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hPeel + have hBlock := + exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_payable_generated_prefix + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) + selector cases' [nativeRevertZeroZeroStmt] body' contract tx storage + initialEvents observableSlots final nativeYul reservedNames bodyStart + bodyEnd fn hSelector hCase hSelectorRange hTagsRange hBodyLower + hPayable hguards hNoWrap hArgs + rcases hBlock with ⟨bodyNative, userBodyStart, hUserBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hUserBody hPreservesUser hProject + rw [hPeel'] + have hResult := hCont hUserBody hPreservesUser hProject + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hResult + +/-- Reserved-context generated-prefix success variant for non-payable selector + hits. The selected-body premises are over the lowered user body `fn.body`, + not over the generated `switchCaseBody fn` wrapper. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_withSwitchIds_generated_prefix_projectResult_eq + (fuel selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (value : EvmYul.Yul.Ast.Literal) : - (projectResult tx initialStorage initialEvents - (.error (.YulHalt state value))).finalMappings = - Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) := by - rfl - -@[simp] theorem projectResult_yulHalt_finalStorageSlot - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 24) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange _ hFn + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 5) reservedNames switchStart cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult (fuel + cases'.length + 24) + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 18) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hPeel + have hBlock := + exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_nonpayable_generated_prefix + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) + selector cases' [nativeRevertZeroZeroStmt] body' contract tx storage + initialEvents observableSlots final nativeYul reservedNames bodyStart + bodyEnd fn hSelector hCase hSelectorRange hTagsRange hBodyLower + hNonPayable hguards hNoWrap hArgs + rcases hBlock with ⟨bodyNative, userBodyStart, hUserBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hUserBody hPreservesUser hProject + rw [hPeel'] + have hResult := hCont hUserBody hPreservesUser hProject + simpa [contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using hResult + +/-- Exact-total-fuel companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_generated_prefix_projectResult_eq`. + +The selected-body execution premise remains over the lowered user body +`fn.body`, while the dispatcher result is stated at an externally supplied +total fuel `fuel'`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_generated_prefix_atFuel_projectResult_eq + (fuel' selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (value : EvmYul.Yul.Ast.Literal) - (slot : Nat) - (account : EvmYul.Account .Yul) - (slotValue : EvmYul.UInt256) - (hAccount : - state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = - some account) - (hSlot : account.storage.find? (natToUInt256 slot) = some slotValue) : - (projectResult tx initialStorage initialEvents - (.error (.YulHalt state value))).finalStorage (IRStorageSlot.ofNat slot) = - slotValue := by - simp [projectResult, projectStorageFromState_accountStorageSlot, - hAccount, hSlot] - -@[simp] theorem projectResult_yulHalt_missingFinalStorageAccountSlot - (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 23 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange _ hFn + have hBlock : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (userBodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + cases'.length + 17) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + simpa [contract] using + (exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_payable_generated_prefix + (fuel' - (cases'.length + 23)) selector + (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage + initialEvents observableSlots final nativeYul reservedNames bodyStart + bodyEnd fn hSelector hCase hSelectorRange hTagsRange hBodyLower + hPayable hguards hNoWrap hArgs) + rcases hBlock with ⟨bodyNative, userBodyStart, hUserBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hUserBody hPreservesUser hProject + let fuel := fuel' - (cases'.length + 23) + have hFuelShape : fuel' = fuel + cases'.length + 23 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 4) reservedNames n0 cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hDispatcherFuel : + fuel + cases'.length + 23 = + (fuel + 4) + cases'.length + 19 := by + omega + have hSwitchFuel : + fuel + cases'.length + 17 = + (fuel + 4) + cases'.length + 13 := by + omega + rw [hDispatcherFuel, hSwitchFuel] + simpa [contract] using hPeel + rw [hPeel'] + have hUserBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final := by + intro pre suffix hCases + simpa [fuel, contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hUserBody pre suffix hCases + have hResult := hCont hUserBody' hPreservesUser hProject + simpa [contract, fuel, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hResult + +/-- Exact-total-fuel companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_generated_prefix_projectResult_eq`. + +The selected-body execution premise remains over the lowered user body +`fn.body`, while the dispatcher result is stated at an externally supplied +total fuel `fuel'`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_generated_prefix_atFuel_projectResult_eq + (fuel' selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 24 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange _ hFn + have hBlock : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (userBodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + cases'.length + 18) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + simpa [contract] using + (exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_nonpayable_generated_prefix + (fuel' - (cases'.length + 24)) selector + (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage + initialEvents observableSlots final nativeYul reservedNames bodyStart + bodyEnd fn hSelector hCase hSelectorRange hTagsRange hBodyLower + hNonPayable hguards hNoWrap hArgs) + rcases hBlock with ⟨bodyNative, userBodyStart, hUserBodyLower, hCont⟩ + refine ⟨reservedNames, n0, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hUserBody hPreservesUser hProject + let fuel := fuel' - (cases'.length + 24) + have hFuelShape : fuel' = fuel + cases'.length + 24 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 5) reservedNames n0 cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 18) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hDispatcherFuel : + fuel + cases'.length + 24 = + (fuel + 5) + cases'.length + 19 := by + omega + have hSwitchFuel : + fuel + cases'.length + 18 = + (fuel + 5) + cases'.length + 13 := by + omega + rw [hDispatcherFuel, hSwitchFuel] + simpa [contract] using hPeel + rw [hPeel'] + have hUserBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final := by + intro pre suffix hCases + simpa [fuel, contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hUserBody pre suffix hCases + have hResult := hCont hUserBody' hPreservesUser hProject + simpa [contract, fuel, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hResult + +/-- Exact-total-fuel reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_withSwitchIds_generated_prefix_projectResult_eq`. + +The selected-body execution premise remains over the lowered user body +`fn.body`, while the dispatcher result is stated at an externally supplied +total fuel `fuel'`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_withSwitchIds_generated_prefix_atFuel_projectResult_eq + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hPayable : fn.payable = true) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 23 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange _ hFn + have hBlock : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (userBodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + EvmYul.Yul.exec ((fuel' - (cases'.length + 23)) + cases'.length + 17) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + simpa [contract] using + (exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_payable_generated_prefix + (fuel' - (cases'.length + 23)) selector + (Backends.freshNativeSwitchId reservedNames switchStart) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage + initialEvents observableSlots final nativeYul reservedNames bodyStart + bodyEnd fn hSelector hCase hSelectorRange hTagsRange hBodyLower + hPayable hguards hNoWrap hArgs) + rcases hBlock with ⟨bodyNative, userBodyStart, hUserBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hUserBody hPreservesUser hProject + let fuel := fuel' - (cases'.length + 23) + have hFuelShape : fuel' = fuel + cases'.length + 23 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 4) reservedNames switchStart cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hDispatcherFuel : + fuel + cases'.length + 23 = + (fuel + 4) + cases'.length + 19 := by + omega + have hSwitchFuel : + fuel + cases'.length + 17 = + (fuel + 4) + cases'.length + 13 := by + omega + rw [hDispatcherFuel, hSwitchFuel] + simpa [contract] using hPeel + rw [hPeel'] + have hUserBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final := by + intro pre suffix hCases + simpa [fuel, contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hUserBody pre suffix hCases + have hResult := hCont hUserBody' hPreservesUser hProject + simpa [contract, fuel, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hResult + +/-- Exact-total-fuel reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_withSwitchIds_generated_prefix_projectResult_eq`. + +The selected-body execution premise remains over the lowered user body +`fn.body`, while the dispatcher result is stated at an externally supplied +total fuel `fuel'`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_withSwitchIds_generated_prefix_atFuel_projectResult_eq + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) + (tx : IRTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (value : EvmYul.Yul.Ast.Literal) - (slot : Nat) - (hAccount : - state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = - none) : - (projectResult tx initialStorage initialEvents - (.error (.YulHalt state value))).finalStorage (IRStorageSlot.ofNat slot) = 0 := by - simp [projectResult, projectStorageFromState_missingAccount, hAccount] - -@[simp] theorem projectResult_yulHalt_missingFinalStorageSlot + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = + (YulTransaction.ofIR tx).functionSelector % + Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) + (hNonPayable : fn.payable = false) + (hguards : DispatchGuardsSafe fn tx) + (hArgs : fn.params.length ≤ tx.args.length) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' bodyNative : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd userBodyStart : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + (cases'.length + 24 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange _ hFn + have hBlock : + ∃ (bodyNative : List EvmYul.Yul.Ast.Stmt) (userBodyStart : Nat), + Backends.lowerStmtsNativeWithSwitchIds reservedNames userBodyStart + fn.body = .ok (bodyNative, bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) bodyNative (some contract)) → + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul → + EvmYul.Yul.exec ((fuel' - (cases'.length + 24)) + cases'.length + 18) + (.Block [Backends.lowerNativeSwitchBlock + Compiler.Proofs.YulGeneration.selectorExpr + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) = + .ok final ∧ + projectResult (YulTransaction.ofIR tx) storage initialEvents + (.ok (final, [])) = nativeYul) := by + simpa [contract] using + (exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_nonpayable_generated_prefix + (fuel' - (cases'.length + 24)) selector + (Backends.freshNativeSwitchId reservedNames switchStart) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage + initialEvents observableSlots final nativeYul reservedNames bodyStart + bodyEnd fn hSelector hCase hSelectorRange hTagsRange hBodyLower + hNonPayable hguards hNoWrap hArgs) + rcases hBlock with ⟨bodyNative, userBodyStart, hUserBodyLower, hCont⟩ + refine ⟨switchStart, cases', midN, body', bodyNative, bodyStart, bodyEnd, + userBodyStart, hLowerCases, hCase, hBodyLower, hUserBodyLower, ?_⟩ + intro hFuel hUserBody hPreservesUser hProject + let fuel := fuel' - (cases'.length + 24) + have hFuelShape : fuel' = fuel + cases'.length + 24 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + have hPeel := + contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + (fuel + 5) reservedNames switchStart cases' body1 inner functions + (YulTransaction.ofIR tx) storage observableSlots hInner + (by simpa [YulTransaction.ofIR_args] using hNoWrap) + have hPeel' : + contractDispatcherExecResult fuel' + contract + (initialState contract (YulTransaction.ofIR tx) storage + observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 18) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract (YulTransaction.ofIR tx) + storage observableSlots).insert "__has_selector" + (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hDispatcherFuel : + fuel + cases'.length + 24 = + (fuel + 5) + cases'.length + 19 := by + omega + have hSwitchFuel : + fuel + cases'.length + 18 = + (fuel + 5) + cases'.length + 13 := by + omega + rw [hDispatcherFuel, hSwitchFuel] + simpa [contract] using hPeel + rw [hPeel'] + have hUserBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (fuel + suffix.length + 10) (.Block bodyNative) + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract + (YulTransaction.ofIR tx) storage observableSlots + (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final := by + intro pre suffix hCases + simpa [fuel, contract, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hUserBody pre suffix hCases + have hResult := hCont hUserBody' hPreservesUser hProject + simpa [contract, fuel, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] + using hResult + +/-- Exact-total-fuel companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_atFuel_projectResult_eq + (fuel' selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (value : EvmYul.Yul.Ast.Literal) - (slot : Nat) - (account : EvmYul.Account .Yul) - (hAccount : - state.sharedState.accountMap.find? (natToAddress tx.thisAddress) = - some account) - (hSlot : account.storage.find? (natToUInt256 slot) = none) : - (projectResult tx initialStorage initialEvents - (.error (.YulHalt state value))).finalStorage (IRStorageSlot.ofNat slot) = 0 := by - simp [projectResult, projectStorageFromState_missingAccountStorageSlot, - hAccount, hSlot] - -@[simp] theorem projectResult_stop + (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + (cases'.length + 19 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .error err) → + projectResult tx storage initialEvents (.error err) = nativeYul → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .error err ∧ + projectResult tx storage initialEvents (.error err) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + ?_, ?_, ?_, ?_⟩ + · exact hLowerCases + · exact hCase + · exact hBodyLower + · intro hFuel hBody hProject + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .error err := by + intro pre suffix hcases + simpa [fuel, contract, Nat.add_assoc] using hBody pre suffix hcases + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + constructor + · rw [hPeel] + exact (exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + fuel selector (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots err nativeYul hSelector hCase hSelectorRange hTagsRange + hBody' hProject).1 + · exact hProject + +/-- Artifact-fixed companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_atFuel_projectResult_eq`. + +This no-reserved-context variant exposes the selected switch-case artifacts +before choosing the concrete error/result pair, matching the reserved-context +artifact theorem below. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_atFuel_artifact_projectResult_eq + (fuel' selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) : - projectResult tx initialStorage initialEvents - (.error (.YulHalt state ⟨0⟩)) = - { success := true - returnValue := none - finalStorage := projectStorageFromState tx state - finalMappings := - Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) - events := initialEvents ++ projectLogsFromState state } := by - simp [projectResult] - -@[simp] theorem projectResult_32ByteReturn + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + (∀ (err : EvmYul.Yul.Exception) (nativeYul : YulResult), + cases'.length + 19 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .error err) → + projectResult tx storage initialEvents (.error err) = nativeYul → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .error err ∧ + projectResult tx storage initialEvents (.error err) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro err nativeYul hFuel hBody hProject + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .error err := by + intro pre suffix hcases + simpa [fuel, contract, Nat.add_assoc] using hBody pre suffix hcases + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + constructor + · rw [hPeel] + exact (exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + fuel selector (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots err nativeYul hSelector hCase hSelectorRange hTagsRange + hBody' hProject).1 + · exact hProject + +/-- Generic selector-hit native execution package for a no-fallback/no-receive +generated dispatcher when the selected native body finishes normally. + +The selected-body execution, switch-temporary freshness, matched-flag +preservation, and final-state projection remain explicit premises; this theorem +packages the dispatcher/prologue/lazy-switch execution around them. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_projectResult_eq + (fuel selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (value : EvmYul.Yul.Ast.Literal) - (hHalt : value ≠ ⟨0⟩) - (hSize : state.sharedState.H_return.size = 32) : - projectResult tx initialStorage initialEvents - (.error (.YulHalt state value)) = - { success := true - returnValue := some (byteArrayWord state.sharedState.H_return 0) - finalStorage := projectStorageFromState tx state - finalMappings := - Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) - events := initialEvents ++ projectLogsFromState state } := by - simp [projectResult, hHalt, hSize] - -@[simp] theorem projectResult_non32ByteReturn + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + ((Backends.nativeSwitchTempsFreshForNativeBodies + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ stmt, stmt ∈ body' → + Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0) ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) → + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, ?_, ?_, ?_⟩ + · exact hCase + · exact hBodyLower + · intro hFresh hBody hStmtPreserves hProject + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq + fuel selector (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots final nativeYul hSelector hCase hSelectorRange hTagsRange + hFresh hBody hStmtPreserves hProject + +/-- Block-preservation companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_projectResult_eq`. + +This packages the dispatcher/prologue/lazy-switch execution while taking the +selected-body matched-word preservation as a block-level fact, avoiding a public +per-statement preservation/freshness obligation at this layer. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_projectResult_eq_preserved + (fuel selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (state : EvmYul.Yul.State) - (value : EvmYul.Yul.Ast.Literal) - (hHalt : value ≠ ⟨0⟩) - (hSize : state.sharedState.H_return.size ≠ 32) : - projectResult tx initialStorage initialEvents - (.error (.YulHalt state value)) = - { success := true - returnValue := some 0 - finalStorage := projectStorageFromState tx state - finalMappings := - Compiler.Proofs.storageAsMappings (projectStorageFromState tx state) - events := initialEvents ++ projectLogsFromState state } := by - simp [projectResult, hHalt, hSize] - -@[simp] theorem projectResult_revert + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' (some contract)) → + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + refine ⟨reservedNames, n0, cases', body', bodyStart, bodyEnd, ?_, ?_, ?_⟩ + · exact hCase + · exact hBodyLower + · intro hBody hPreservesMatched hProject + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_preserved + fuel selector (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots final nativeYul hSelector hCase hSelectorRange hTagsRange + hBody hPreservesMatched hProject + +/-- Exact-total-fuel companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_atFuel_projectResult_eq + (fuel' selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) : - projectResult tx initialStorage initialEvents - (.error EvmYul.Yul.Exception.Revert) = - { success := false - returnValue := none - finalStorage := initialStorage - finalMappings := Compiler.Proofs.storageAsMappings initialStorage - events := initialEvents } := by - rfl - -@[simp] theorem projectResult_revert_events + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + (cases'.length + 19 ≤ fuel' → + (Backends.nativeSwitchTempsFreshForNativeBodies + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ stmt, stmt ∈ body' → + Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0) ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) → + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + ?_, ?_, ?_, ?_⟩ + · exact hLowerCases + · exact hCase + · exact hBodyLower + · intro hFuel hFresh hBody hStmtPreserves hProject + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final := by + intro pre suffix hcases + simpa [fuel, contract, Nat.add_assoc] using hBody pre suffix hcases + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq + fuel selector (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots final nativeYul hSelector hCase hSelectorRange hTagsRange + hFresh hBody' hStmtPreserves hProject + +/-- Exact-total-fuel companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_projectResult_eq_preserved`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_atFuel_projectResult_eq_preserved + (fuel' selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) : - (projectResult tx initialStorage initialEvents - (.error EvmYul.Yul.Exception.Revert)).events = - initialEvents := by - rfl - -@[simp] theorem projectResult_revert_success + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + (cases'.length + 19 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' (some contract)) → + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + ?_, ?_, ?_, ?_⟩ + · exact hLowerCases + · exact hCase + · exact hBodyLower + · intro hFuel hBody hPreservesMatched hProject + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final := by + intro pre suffix hcases + simpa [fuel, contract, Nat.add_assoc] using hBody pre suffix hcases + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_preserved + fuel selector (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots final nativeYul hSelector hCase hSelectorRange hTagsRange + hBody' hPreservesMatched hProject + +/-- Polymorphic-final companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_atFuel_projectResult_eq_preserved`. + +The lowered selector-hit artifacts do not depend on the eventual selected-body +result, so this exposes one artifact package with a continuation that accepts +any normal selected-case result. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_atFuel_projectResult_eq_preserved_forall + (fuel' selector : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) : - (projectResult tx initialStorage initialEvents - (.error EvmYul.Yul.Exception.Revert)).success = false := by - rfl - -@[simp] theorem projectResult_revert_returnValue + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNative + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok [.Block inner]) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (reservedNames : List String) (n0 : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (midN : Nat) (body' : List EvmYul.Yul.Ast.Stmt) + (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + (∀ final nativeYul, + cases'.length + 19 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames n0)) + (EvmYul.UInt256.ofNat 1) body' (some contract)) → + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + funcs inner selector fn hLower hFind + refine ⟨reservedNames, n0, cases', midN, body', bodyStart, bodyEnd, + ?_, ?_, ?_, ?_⟩ + · exact hLowerCases + · exact hCase + · exact hBodyLower + · intro final nativeYul hFuel hBody hPreservesMatched hProject + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames n0 + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames n0) + nativeSwitchHasSelectorStore) = .ok final := by + intro pre suffix hcases + simpa [fuel, contract, Nat.add_assoc] using hBody pre suffix hcases + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames n0) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_preserved + fuel selector (Backends.freshNativeSwitchId reservedNames n0) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots final nativeYul hSelector hCase hSelectorRange hTagsRange + hBody' hPreservesMatched hProject + +/-- Reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_projectResult_eq + (fuel selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) : - (projectResult tx initialStorage initialEvents - (.error EvmYul.Yul.Exception.Revert)).returnValue = none := by - rfl - -@[simp] theorem projectResult_revert_finalMappings + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .error err) → + projectResult tx storage initialEvents (.error err) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + .error err ∧ + projectResult tx storage initialEvents (.error err) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, ?_, ?_, ?_⟩ + · exact hCase + · exact hBodyLower + · intro hBody hProject + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots err nativeYul hSelector hCase hSelectorRange hTagsRange + hBody hProject + +/-- Exact-total-fuel companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_atFuel_projectResult_eq + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) : - (projectResult tx initialStorage initialEvents - (.error EvmYul.Yul.Exception.Revert)).finalMappings = - Compiler.Proofs.storageAsMappings initialStorage := by - rfl - -@[simp] theorem projectResult_revert_finalStorageSlot + (storage : IRStorageSlot → IRStorageWord) + (initialEvents : List (List Nat)) + (observableSlots : List Nat) + (err : EvmYul.Yul.Exception) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + (cases'.length + 19 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .error err) → + projectResult tx storage initialEvents (.error err) = nativeYul → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .error err ∧ + projectResult tx storage initialEvents (.error err) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + refine ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + ?_, ?_, ?_, ?_⟩ + · exact hLowerCases + · exact hCase + · exact hBodyLower + · intro hFuel hBody hProject + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .error err := by + intro pre suffix hcases + simpa [fuel, contract, Nat.add_assoc] using hBody pre suffix hcases + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + constructor + · rw [hPeel] + exact (exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots err nativeYul hSelector hCase hSelectorRange hTagsRange + hBody' hProject).1 + · exact hProject + +/-- Artifact-fixed companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_atFuel_projectResult_eq`. + +The selected switch-case artifacts are exposed before choosing the concrete +error and projected native result. This is useful for halt-channel bodies, +where the selected-body execution itself produces the `YulHalt` state that must +be fed into the dispatcher error continuation. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_atFuel_artifact_projectResult_eq + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (slot : Nat) : - (projectResult tx initialStorage initialEvents - (.error EvmYul.Yul.Exception.Revert)).finalStorage (IRStorageSlot.ofNat slot) = - initialStorage (IRStorageSlot.ofNat slot) := by - rfl - -@[simp] theorem projectResult_hardError + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + (∀ (err : EvmYul.Yul.Exception) (nativeYul : YulResult), + cases'.length + 19 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .error err) → + projectResult tx storage initialEvents (.error err) = nativeYul → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .error err ∧ + projectResult tx storage initialEvents (.error err) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + refine ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + hLowerCases, hCase, hBodyLower, ?_⟩ + intro err nativeYul hFuel hBody hProject + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .error err := by + intro pre suffix hcases + simpa [fuel, contract, Nat.add_assoc] using hBody pre suffix hcases + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + constructor + · rw [hPeel] + exact (exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots err nativeYul hSelector hCase hSelectorRange hTagsRange + hBody' hProject).1 + · exact hProject + +/-- Reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_projectResult_eq + (fuel selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (err : EvmYul.Yul.Exception) - (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : - projectResult tx initialStorage initialEvents (.error err) = - { success := false - returnValue := none - finalStorage := initialStorage - finalMappings := Compiler.Proofs.storageAsMappings initialStorage - events := initialEvents } := by - cases err with - | YulHalt state value => - exact False.elim (hNotHalt state value rfl) - | InvalidArguments => rfl - | NotEncodableRLP => rfl - | InvalidInstruction => rfl - | OutOfFuel => rfl - | StaticModeViolation => rfl - | MissingContract s => rfl - | MissingContractFunction s => rfl - | InvalidExpression => rfl - | YulEXTCODESIZENotImplemented => rfl - | Revert => rfl - -@[simp] theorem projectResult_hardError_success + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + ((Backends.nativeSwitchTempsFreshForNativeBodies + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ stmt, stmt ∈ body' → + Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart) ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) → + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, ?_, ?_, ?_⟩ + · exact hCase + · exact hBodyLower + · intro hFresh hBody hStmtPreserves hProject + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots final nativeYul hSelector hCase hSelectorRange hTagsRange + hFresh hBody hStmtPreserves hProject + +/-- Block-preservation reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_projectResult_eq_preserved + (fuel selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (err : EvmYul.Yul.Exception) - (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : - (projectResult tx initialStorage initialEvents (.error err)).success = false := by - cases err with - | YulHalt state value => - exact False.elim (hNotHalt state value rfl) - | InvalidArguments => rfl - | NotEncodableRLP => rfl - | InvalidInstruction => rfl - | OutOfFuel => rfl - | StaticModeViolation => rfl - | MissingContract s => rfl - | MissingContractFunction s => rfl - | InvalidExpression => rfl - | YulEXTCODESIZENotImplemented => rfl - | Revert => rfl - -@[simp] theorem projectResult_hardError_returnValue + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + ((∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) body' (some contract)) → + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul → + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + refine ⟨switchStart, cases', body', bodyStart, bodyEnd, ?_, ?_, ?_⟩ + · exact hCase + · exact hBodyLower + · intro hBody hPreservesMatched hProject + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_preserved + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots final nativeYul hSelector hCase hSelectorRange hTagsRange + hBody hPreservesMatched hProject + +/-- Exact-total-fuel reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_atFuel_projectResult_eq + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (err : EvmYul.Yul.Exception) - (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : - (projectResult tx initialStorage initialEvents (.error err)).returnValue = none := by - cases err with - | YulHalt state value => - exact False.elim (hNotHalt state value rfl) - | InvalidArguments => rfl - | NotEncodableRLP => rfl - | InvalidInstruction => rfl - | OutOfFuel => rfl - | StaticModeViolation => rfl - | MissingContract s => rfl - | MissingContractFunction s => rfl - | InvalidExpression => rfl - | YulEXTCODESIZENotImplemented => rfl - | Revert => rfl - -@[simp] theorem projectResult_hardError_finalStorageSlot + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + (cases'.length + 19 ≤ fuel' → + (Backends.nativeSwitchTempsFreshForNativeBodies + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ stmt, stmt ∈ body' → + Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart) ∉ + Backends.nativeStmtWriteNames stmt → + NativeStmtPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) stmt (some contract)) → + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + refine ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + ?_, ?_, ?_, ?_⟩ + · exact hLowerCases + · exact hCase + · exact hBodyLower + · intro hFuel hFresh hBody hStmtPreserves hProject + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final := by + intro pre suffix hcases + simpa [fuel, contract, Nat.add_assoc] using hBody pre suffix hcases + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots final nativeYul hSelector hCase hSelectorRange hTagsRange + hFresh hBody' hStmtPreserves hProject + +/-- Exact-total-fuel reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_projectResult_eq_preserved`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_atFuel_projectResult_eq_preserved + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (err : EvmYul.Yul.Exception) - (slot : Nat) - (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : - (projectResult tx initialStorage initialEvents (.error err)).finalStorage (IRStorageSlot.ofNat slot) = - initialStorage (IRStorageSlot.ofNat slot) := by - cases err with - | YulHalt state value => - exact False.elim (hNotHalt state value rfl) - | InvalidArguments => rfl - | NotEncodableRLP => rfl - | InvalidInstruction => rfl - | OutOfFuel => rfl - | StaticModeViolation => rfl - | MissingContract s => rfl - | MissingContractFunction s => rfl - | InvalidExpression => rfl - | YulEXTCODESIZENotImplemented => rfl - | Revert => rfl - -@[simp] theorem projectResult_hardError_finalMappings + (observableSlots : List Nat) + (final : EvmYul.Yul.State) (nativeYul : YulResult) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + (cases'.length + 19 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) body' (some contract)) → + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + refine ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + ?_, ?_, ?_, ?_⟩ + · exact hLowerCases + · exact hCase + · exact hBodyLower + · intro hFuel hBody hPreservesMatched hProject + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final := by + intro pre suffix hcases + simpa [fuel, contract, Nat.add_assoc] using hBody pre suffix hcases + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_preserved + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots final nativeYul hSelector hCase hSelectorRange hTagsRange + hBody' hPreservesMatched hProject + +/-- Polymorphic-final reserved-context companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_atFuel_projectResult_eq_preserved`. + +The reserved-name lowering artifacts are independent of the selected-body +normal result, so this exposes a single artifact package with a continuation +that accepts any `final/nativeYul`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_atFuel_projectResult_eq_preserved_forall + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) (fn : IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (err : EvmYul.Yul.Exception) - (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : - (projectResult tx initialStorage initialEvents (.error err)).finalMappings = - Compiler.Proofs.storageAsMappings initialStorage := by - cases err with - | YulHalt state value => - exact False.elim (hNotHalt state value rfl) - | InvalidArguments => rfl - | NotEncodableRLP => rfl - | InvalidInstruction => rfl - | OutOfFuel => rfl - | StaticModeViolation => rfl - | MissingContract s => rfl - | MissingContractFunction s => rfl - | InvalidExpression => rfl - | YulEXTCODESIZENotImplemented => rfl - | Revert => rfl - -@[simp] theorem projectResult_hardError_events + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun f => f.selector == selector) = some fn) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat) + (body' : List EvmYul.Yul.Ast.Stmt) (bodyStart bodyEnd : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + cases'.find? (fun entry => entry.1 == selector) = + some (selector, body') ∧ + Backends.lowerStmtsNativeWithSwitchIds reservedNames bodyStart + (switchCaseBody fn) = .ok (body', bodyEnd) ∧ + (∀ final nativeYul, + cases'.length + 19 ≤ fuel' → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec (((fuel' - (cases'.length + 19)) + 1) + + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final) → + (∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + NativeBlockPreservesWord + (Backends.nativeSwitchMatchedTempName + (Backends.freshNativeSwitchId reservedNames switchStart)) + (EvmYul.UInt256.ofNat 1) body' (some contract)) → + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .ok final ∧ + projectResult tx storage initialEvents (.ok (final, [])) = nativeYul) := by + obtain ⟨body1, switchStart, cases', midN, body', bodyStart, bodyEnd, + hInner, hLowerCases, hCase, hBodyLower⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + reservedNames n0 funcs inner next selector fn hLower hFind + refine ⟨switchStart, cases', midN, body', bodyStart, bodyEnd, + ?_, ?_, ?_, ?_⟩ + · exact hLowerCases + · exact hCase + · exact hBodyLower + · intro final nativeYul hFuel hBody hPreservesMatched hProject + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hBody' : + ∀ pre suffix, cases' = pre ++ (selector, body') :: suffix → + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) (.Block body') + (some contract) + (nativeSwitchStoreMarkedPrefixStateForId contract tx storage + observableSlots (Backends.freshNativeSwitchId reservedNames switchStart) + nativeSwitchHasSelectorStore) = .ok final := by + intro pre suffix hcases + simpa [fuel, contract, Nat.add_assoc] using hBody pre suffix hcases + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_preserved + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) selector + cases' [nativeRevertZeroZeroStmt] body' contract tx storage initialEvents + observableSlots final nativeYul hSelector hCase hSelectorRange hTagsRange + hBody' hPreservesMatched hProject + +/-- Reserved-context variant of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_projectResult_eq`. + +This is the selector-miss package needed when the generated dispatcher is lowered +under the emitted runtime's reserved-name context, as in the mapping-helper +runtime path. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_withSwitchIds_projectResult_eq + (fuel selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) (tx : YulTransaction) - (initialStorage : IRStorageSlot → IRStorageWord) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) - (err : EvmYul.Yul.Exception) - (hNotHalt : ∀ state value, err ≠ EvmYul.Yul.Exception.YulHalt state value) : - (projectResult tx initialStorage initialEvents (.error err)).events = - initialEvents := by - cases err with - | YulHalt state value => - exact False.elim (hNotHalt state value rfl) - | InvalidArguments => rfl - | NotEncodableRLP => rfl - | InvalidInstruction => rfl - | OutOfFuel => rfl - | StaticModeViolation => rfl - | MissingContract s => rfl - | MissingContractFunction s => rfl - | InvalidExpression => rfl - | YulEXTCODESIZENotImplemented => rfl - | Revert => rfl + (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) + (hSelector : + selector = tx.functionSelector % Compiler.Constants.selectorModulus) + (hFind : funcs.find? (fun fn => fn.selector == selector) = none) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) + (hSelectorRange : selector < EvmYul.UInt256.size) + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + { success := false + returnValue := none + finalStorage := storage + finalMappings := Compiler.Proofs.storageAsMappings storage + events := initialEvents } := by + obtain ⟨body1, switchStart, cases', midN, hInner, hLowerCases⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered_withSwitchIds + reservedNames n0 funcs inner next hLower + refine ⟨switchStart, cases', midN, ?_, ?_, ?_⟩ + · exact hLowerCases + · let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hLowerFind : + cases'.find? (fun entry => entry.1 == selector) = none := + lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function + reservedNames (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + selector funcs cases' hLowerCases hFind + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) cases' + contract tx storage observableSlots hSelector hLowerFind hSelectorRange + hTagsRange + · simp -/-- Guarded selector-miss execution for a fully lowered native switch block, - lifted through Verity's projected native result boundary. The generated - `revert(0, 0)` default both executes through the actual native step - relation and projects as a failed call with no return word and rolled-back - observable storage. -/ -theorem exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult - (fuel selector switchId : Nat) - (cases : List (Nat × List EvmYul.Yul.Ast.Stmt)) - (contract : EvmYul.Yul.Ast.YulContract) +/-- Exact-total-fuel reserved-context selector-miss companion of +`contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_withSwitchIds_projectResult_eq`. -/ +theorem contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_withSwitchIds_atFuel_projectResult_eq + (fuel' selector : Nat) + (reservedNames : List String) (n0 : Nat) + (funcs : List IRFunction) + (inner : List EvmYul.Yul.Ast.Stmt) (next : Nat) + (functions : NativeFunctionMap) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) (observableSlots : List Nat) + (hLower : + Backends.lowerStmtsNativeWithSwitchIds reservedNames n0 + [Compiler.CodegenCommon.buildSwitch funcs none none] = + .ok ([.Block inner], next)) (hSelector : selector = tx.functionSelector % Compiler.Constants.selectorModulus) - (hFind : cases.find? (fun entry => entry.1 == selector) = none) + (hFind : funcs.find? (fun fn => fn.selector == selector) = none) + (hNoWrap : 4 + tx.args.length * 32 < EvmYul.UInt256.size) (hSelectorRange : selector < EvmYul.UInt256.size) - (hTagsRange : - ∀ tag body, (tag, body) ∈ cases → tag < EvmYul.UInt256.size) : - EvmYul.Yul.exec (fuel + cases.length + 12) - (Backends.lowerNativeSwitchBlock - Compiler.Proofs.YulGeneration.selectorExpr switchId cases - [nativeRevertZeroZeroStmt]) - (some contract) - (nativeSwitchInitialOkState contract tx storage observableSlots) = - .error EvmYul.Yul.Exception.Revert ∧ - (projectResult tx storage initialEvents - (.error EvmYul.Yul.Exception.Revert)).success = false ∧ - (projectResult tx storage initialEvents - (.error EvmYul.Yul.Exception.Revert)).returnValue = none ∧ - (∀ slot, - (projectResult tx storage initialEvents - (.error EvmYul.Yul.Exception.Revert)).finalStorage (IRStorageSlot.ofNat slot) = - storage (IRStorageSlot.ofNat slot)) := by - refine ⟨?_, ?_, ?_, ?_⟩ - · exact exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_fuel - fuel selector switchId cases contract tx storage observableSlots - hSelector hFind hSelectorRange hTagsRange - · simp - · simp - · intro slot - simp + (hFunctionSelectorsRange : + ∀ fn, fn ∈ funcs → fn.selector < EvmYul.UInt256.size) : + ∃ (switchStart : Nat) + (cases' : List (Nat × List EvmYul.Yul.Ast.Stmt)) (midN : Nat), + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + Backends.lowerSwitchCasesNativeWithSwitchIds reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) + (buildSwitchSourceCases funcs) = .ok (cases', midN) ∧ + (cases'.length + 19 ≤ fuel' → + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + .error EvmYul.Yul.Exception.Revert ∧ + projectResult tx storage initialEvents + (.error EvmYul.Yul.Exception.Revert) = + { success := false + returnValue := none + finalStorage := storage + finalMappings := Compiler.Proofs.storageAsMappings storage + events := initialEvents }) := by + obtain ⟨body1, switchStart, cases', midN, hInner, hLowerCases⟩ := + buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered_withSwitchIds + reservedNames n0 funcs inner next hLower + refine ⟨switchStart, cases', midN, ?_, ?_⟩ + · exact hLowerCases + · intro hFuel + let fuel := fuel' - (cases'.length + 19) + have hFuelShape : fuel' = fuel + cases'.length + 19 := by + dsimp [fuel] + exact (Nat.sub_add_cancel hFuel).symm + let contract : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hLowerFind : + cases'.find? (fun entry => entry.1 == selector) = none := + lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function + reservedNames (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + selector funcs cases' hLowerCases hFind + have hTagsEq : + cases'.map (·.1) = (buildSwitchSourceCases funcs).map (·.1) := + Backends.lowerSwitchCasesNativeWithSwitchIds_tags_eq reservedNames + (Backends.freshNativeSwitchId reservedNames switchStart + 1) midN + (buildSwitchSourceCases funcs) cases' hLowerCases + have hTagsRange : + ∀ tag body, (tag, body) ∈ cases' → tag < EvmYul.UInt256.size := by + intro tag body hmem + have hTagMem : tag ∈ cases'.map (·.1) := by + exact List.mem_map_of_mem (f := Prod.fst) hmem + rw [hTagsEq] at hTagMem + simp [buildSwitchSourceCases] at hTagMem + rcases hTagMem with ⟨fn, hFn, hTag⟩ + subst hTag + exact hFunctionSelectorsRange fn hFn + have hPeel : + contractDispatcherExecResult fuel' + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + rw [hFuelShape] + have hPeelStructural : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + let contract' : EvmYul.Yul.Ast.YulContract := + { dispatcher := .Block [.Block inner], functions := functions } + have hFuelShape' : + fuel + cases'.length + 19 = + Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16))) := by + omega + have hDispatcherPeel : + contractDispatcherExecResult (fuel + cases'.length + 19) + contract' (initialState contract' tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract') + (nativeSwitchInitialOkState contract' tx storage observableSlots) := by + rw [hFuelShape'] + change + contractDispatcherExecResult + (Nat.succ (Nat.succ (Nat.succ (fuel + cases'.length + 16)))) + { dispatcher := .Block [.Block inner], functions := functions } + (initialState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) = + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots) + rw [contractDispatcherExecResult_block_dispatcher_eq_exec_block + (Nat.succ (fuel + cases'.length + 16)) [.Block inner] functions + tx storage observableSlots] + rw [exec_singleton_block_eq_exec_block (fuel + cases'.length + 16) inner + (some { dispatcher := .Block [.Block inner], functions := functions }) + (nativeSwitchInitialOkState + { dispatcher := .Block [.Block inner], functions := functions } + tx storage observableSlots)] + calc + contractDispatcherExecResult (fuel + cases'.length + 19) + contract (initialState contract tx storage observableSlots) + = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block inner) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := hDispatcherPeel + _ = EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block + [EvmYul.Yul.Ast.Stmt.Let ["__has_selector"] + (some + (Backends.lowerExprNative + (YulExpr.call "iszero" + [YulExpr.call "lt" + [YulExpr.call "calldatasize" [], + YulExpr.lit 4]]))), + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative + (YulExpr.call "iszero" [YulExpr.ident "__has_selector"])) + body1, + EvmYul.Yul.Ast.Stmt.If + (Backends.lowerExprNative (YulExpr.ident "__has_selector")) + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]]) + (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots) := by + exact congrArg + (fun body => + EvmYul.Yul.exec (fuel + cases'.length + 17) + (.Block body) (some contract) + (nativeSwitchInitialOkState contract tx storage observableSlots)) + hInner + _ = EvmYul.Yul.exec (fuel + cases'.length + 13) + (.Block + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]]) + (some contract) + ((nativeSwitchInitialOkState contract tx storage observableSlots).insert + "__has_selector" (EvmYul.UInt256.ofNat 1)) := by + have hExec := + exec_block_letSelector_if1Skip_if2Take_initialState_fuel + (fuel + cases'.length + 5) contract tx storage observableSlots + "__has_selector" body1 + [Backends.lowerNativeSwitchBlock + (YulExpr.call "shr" + [YulExpr.lit Compiler.Constants.selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0]]) + (Backends.freshNativeSwitchId reservedNames switchStart) cases' + [nativeRevertZeroZeroStmt]] + hNoWrap + simpa only [Nat.add_assoc] using hExec + exact hPeelStructural + constructor + · rw [hPeel] + exact exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_error + fuel selector (Backends.freshNativeSwitchId reservedNames switchStart) cases' + contract tx storage observableSlots hSelector hLowerFind hSelectorRange + hTagsRange + · simp /-- The two generated SimpleStorage selector tags fit in one EVM word. -/ private theorem simpleStorageSelectors_tagsRange @@ -13774,7 +33579,7 @@ private theorem simpleStorageSelectors_tagsRange selector set. This specializes the generic lowered-switch miss theorem to the two generated SimpleStorage selectors, discharging the selector tag word-range premise by computation. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_find_none_with_revert_default_projectResult +private theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_find_none_with_revert_default_projectResult (fuel selector switchId : Nat) (storeBody retrieveBody : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) @@ -13821,7 +33626,7 @@ This packages the `revert(0, 0)` default branch in the shape needed by the dispatcher bridge: native execution reaches EVMYulLean's `Revert` exception, and Verity's projection rolls the call back to failed success, no return value, unchanged storage/mappings, and unchanged events. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_find_none_with_revert_default_projectResult_eq +private theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_find_none_with_revert_default_projectResult_eq (fuel selector switchId : Nat) (storeBody retrieveBody : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) @@ -13852,14 +33657,15 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_find_none_with_revert finalStorage := storage finalMappings := Compiler.Proofs.storageAsMappings storage events := initialEvents } := by - rcases - exec_lowerNativeSwitchBlock_simpleStorageSelectors_find_none_with_revert_default_projectResult - fuel selector switchId storeBody retrieveBody contract tx storage - initialEvents observableSlots hSelector hFind hSelectorRange with - ⟨hExec, _hSuccess, _hReturn, _hStorage⟩ - exact ⟨hExec, by simp⟩ + exact + exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq + fuel selector switchId + [(0x6057361d, storeBody), (0x2e64cec1, retrieveBody)] + contract tx storage initialEvents observableSlots + hSelector hFind hSelectorRange + (simpleStorageSelectors_tagsRange storeBody retrieveBody) -def simpleStorageRevertProjectedResult +private def simpleStorageRevertProjectedResult (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) : YulResult := { success := false @@ -13872,7 +33678,7 @@ def simpleStorageRevertProjectedResult `store(uint256)` selector arm. Naming this body lets later dispatcher bridge lemmas specialize the selector-switch theorem without carrying arbitrary body parameters. -/ -def simpleStorageNativeStoreBody : List EvmYul.Yul.Ast.Stmt := +private def simpleStorageNativeStoreBody : List EvmYul.Yul.Ast.Stmt := [ .If (lowerExprNative (.call "callvalue" [])) [nativeRevertZeroZeroStmt], .If (lowerExprNative (.call "lt" [.call "calldatasize" [], .lit 36])) [nativeRevertZeroZeroStmt], @@ -13882,7 +33688,7 @@ def simpleStorageNativeStoreBody : List EvmYul.Yul.Ast.Stmt := /-- Concrete lowered native body for the generated SimpleStorage `retrieve()` selector arm. -/ -def simpleStorageNativeRetrieveBody : List EvmYul.Yul.Ast.Stmt := +private def simpleStorageNativeRetrieveBody : List EvmYul.Yul.Ast.Stmt := [ .If (lowerExprNative (.call "callvalue" [])) [nativeRevertZeroZeroStmt], .If (lowerExprNative (.call "lt" [.call "calldatasize" [], .lit 4])) [nativeRevertZeroZeroStmt], @@ -13891,7 +33697,7 @@ def simpleStorageNativeRetrieveBody : List EvmYul.Yul.Ast.Stmt := (.call "mstore" [.lit 0, .call "sload" [.lit 0]])), .ExprStmtCall (lowerExprNative (.call "return" [.lit 0, .lit 32])) ] -def simpleStorageNativeSelectorCases : +private def simpleStorageNativeSelectorCases : List (Nat × List EvmYul.Yul.Ast.Stmt) := [(0x6057361d, simpleStorageNativeStoreBody), (0x2e64cec1, simpleStorageNativeRetrieveBody)] @@ -13903,7 +33709,7 @@ This removes two bookkeeping premises from the default-branch bridge case: callers no longer have to introduce a separate selector witness or prove that the 4-byte selector fits in an EVM word. Both facts follow from the transaction selector modulus bound used by the public end-to-end theorem. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_tx_find_none_with_revert_default_projectResult_eq +private theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_tx_find_none_with_revert_default_projectResult_eq (fuel switchId : Nat) (storeBody retrieveBody : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) @@ -13951,7 +33757,7 @@ This is the branch shape needed by the dispatcher bridge case split: once the transaction selector is known to be neither generated selector, the concrete `find? = none` premise is discharged internally before executing the actual native lowered switch relation. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_tx_miss_with_revert_default_projectResult_eq +private theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_tx_miss_with_revert_default_projectResult_eq (fuel switchId : Nat) (storeBody retrieveBody : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) @@ -13991,7 +33797,7 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_tx_miss_with_revert_d selector switch, with both generated selector bodies fixed to their native lowered shapes. This is the default branch theorem needed by the bridge once the outer dispatcher has exposed the inner selector switch. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageConcrete_tx_miss_with_revert_default_projectResult_eq +private theorem exec_lowerNativeSwitchBlock_simpleStorageConcrete_tx_miss_with_revert_default_projectResult_eq (fuel switchId : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) @@ -14026,7 +33832,7 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageConcrete_tx_miss_with_revert_de selector set. This specializes the generic lowered-switch hit theorem to `store(uint256)`, discharging the computed selector lookup and selector tag word-range premises. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_fuel +private theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_fuel (fuel switchId : Nat) (storeBody retrieveBody : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) @@ -14070,7 +33876,7 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_fuel lifting the SimpleStorage store-hit selector specialization to states already carrying additional bindings (e.g. the dispatcher's `__has_selector := 1`). -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_store_fuel +private theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_store_fuel (fuel switchId : Nat) (storeBody retrieveBody : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) @@ -14115,7 +33921,7 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_store (simpleStorageSelectors_tagsRange storeBody retrieveBody) hBody -def simpleStorageStoreHaltProjectedResult +private def simpleStorageStoreHaltProjectedResult (tx : YulTransaction) (initialEvents : List (List Nat)) (haltState : EvmYul.Yul.State) : YulResult := @@ -14132,7 +33938,7 @@ def simpleStorageStoreHaltProjectedResult This removes the switch-case wrapper from later bridge obligations: callers can prove the selected body once for every possible decomposition, then consume one exact native `YulResult` equality at the full lowered-switch boundary. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_projectResult_eq +private theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_projectResult_eq (fuel switchId : Nat) (storeBody retrieveBody : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) @@ -14146,14 +33952,11 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_projectResu (hBody : ∀ pre suffix, [(0x6057361d, storeBody), (0x2e64cec1, retrieveBody)] = pre ++ (0x6057361d, storeBody) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) - (.Block storeBody) (some contract) - ((nativeSwitchPrefixFinalState contract tx storage observableSlots - (Backends.nativeSwitchDiscrTempName switchId) - (Backends.nativeSwitchMatchedTempName switchId)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1)) = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) + (.Block storeBody) (some contract) + (nativeSwitchMarkedPrefixStateForId contract tx storage + observableSlots switchId) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) (hProject : projectResult tx storage initialEvents (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = @@ -14171,15 +33974,20 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_projectResu projectResult tx storage initialEvents (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = simpleStorageStoreHaltProjectedResult tx initialEvents haltState := by - refine ⟨?_, hProject⟩ exact - exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_fuel - fuel switchId storeBody retrieveBody contract tx storage observableSlots - (EvmYul.Yul.Exception.YulHalt haltState haltValue) hSelector - hBody + exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq + fuel 0x6057361d switchId + [(0x6057361d, storeBody), (0x2e64cec1, retrieveBody)] + [nativeRevertZeroZeroStmt] 0x6057361d storeBody contract tx storage + initialEvents observableSlots + (EvmYul.Yul.Exception.YulHalt haltState haltValue) + (simpleStorageStoreHaltProjectedResult tx initialEvents haltState) + hSelector (by simp) (by norm_num [EvmYul.UInt256.size]) + (simpleStorageSelectors_tagsRange storeBody retrieveBody) + hBody hProject /-- Concrete SimpleStorage store-selector hit execution. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageConcrete_store_hit_projectResult_eq +private theorem exec_lowerNativeSwitchBlock_simpleStorageConcrete_store_hit_projectResult_eq (fuel switchId : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) @@ -14193,14 +34001,11 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageConcrete_store_hit_projectResul (hBody : ∀ pre suffix, simpleStorageNativeSelectorCases = pre ++ (0x6057361d, simpleStorageNativeStoreBody) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) - (.Block simpleStorageNativeStoreBody) (some contract) - ((nativeSwitchPrefixFinalState contract tx storage observableSlots - (Backends.nativeSwitchDiscrTempName switchId) - (Backends.nativeSwitchMatchedTempName switchId)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1)) = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) + (.Block simpleStorageNativeStoreBody) (some contract) + (nativeSwitchMarkedPrefixStateForId contract tx storage + observableSlots switchId) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) (hProject : projectResult tx storage initialEvents (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = @@ -14228,7 +34033,7 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageConcrete_store_hit_projectResul (by simpa [simpleStorageNativeSelectorCases] using hBody) hProject /-- Retrieve-selector hit execution for the concrete SimpleStorage dispatcher. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_error_fuel +private theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_error_fuel (fuel switchId : Nat) (storeBody retrieveBody : List EvmYul.Yul.Ast.Stmt) (contract : EvmYul.Yul.Ast.YulContract) @@ -14269,7 +34074,7 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_error_fu (simpleStorageSelectors_tagsRange storeBody retrieveBody) hBody -def simpleStorageRetrieveHaltProjectedResult +private def simpleStorageRetrieveHaltProjectedResult (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) @@ -14288,29 +34093,22 @@ def simpleStorageRetrieveHaltProjectedResult /-- Retrieve-selector hit execution for the concrete SimpleStorage dispatcher, packaged with the exact projected result of the selected getter body. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_projectResult_eq +private theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_projectResult_eq (fuel switchId : Nat) (storeBody retrieveBody : List EvmYul.Yul.Ast.Stmt) - (contract : EvmYul.Yul.Ast.YulContract) - (tx : YulTransaction) - (storage : IRStorageSlot → IRStorageWord) - (initialEvents : List (List Nat)) - (observableSlots : List Nat) - (haltState : EvmYul.Yul.State) + (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) (initialEvents : List (List Nat)) + (observableSlots : List Nat) (haltState : EvmYul.Yul.State) (haltValue : EvmYul.Yul.Ast.Literal) - (hSelector : - 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) + (hSelector : 0x2e64cec1 = tx.functionSelector % Compiler.Constants.selectorModulus) (hBody : ∀ pre suffix, [(0x6057361d, storeBody), (0x2e64cec1, retrieveBody)] = pre ++ (0x2e64cec1, retrieveBody) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) - (.Block retrieveBody) (some contract) - ((nativeSwitchPrefixFinalState contract tx storage observableSlots - (Backends.nativeSwitchDiscrTempName switchId) - (Backends.nativeSwitchMatchedTempName switchId)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1)) = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) + (.Block retrieveBody) (some contract) + (nativeSwitchMarkedPrefixStateForId contract tx storage + observableSlots switchId) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) (hProject : projectResult tx storage initialEvents (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = @@ -14330,15 +34128,21 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_projectR (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = simpleStorageRetrieveHaltProjectedResult tx storage initialEvents observableSlots haltState := by - refine ⟨?_, hProject⟩ exact - exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_error_fuel - fuel switchId storeBody retrieveBody contract tx storage observableSlots - (EvmYul.Yul.Exception.YulHalt haltState haltValue) hSelector - hBody + exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq + fuel 0x2e64cec1 switchId + [(0x6057361d, storeBody), (0x2e64cec1, retrieveBody)] + [nativeRevertZeroZeroStmt] 0x2e64cec1 retrieveBody contract tx storage + initialEvents observableSlots + (EvmYul.Yul.Exception.YulHalt haltState haltValue) + (simpleStorageRetrieveHaltProjectedResult tx storage initialEvents + observableSlots haltState) + hSelector (by simp) (by norm_num [EvmYul.UInt256.size]) + (simpleStorageSelectors_tagsRange storeBody retrieveBody) + hBody hProject /-- Concrete SimpleStorage retrieve-selector hit execution. -/ -theorem exec_lowerNativeSwitchBlock_simpleStorageConcrete_retrieve_hit_projectResult_eq +private theorem exec_lowerNativeSwitchBlock_simpleStorageConcrete_retrieve_hit_projectResult_eq (fuel switchId : Nat) (contract : EvmYul.Yul.Ast.YulContract) (tx : YulTransaction) @@ -14352,14 +34156,11 @@ theorem exec_lowerNativeSwitchBlock_simpleStorageConcrete_retrieve_hit_projectRe (hBody : ∀ pre suffix, simpleStorageNativeSelectorCases = pre ++ (0x2e64cec1, simpleStorageNativeRetrieveBody) :: suffix → - EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) - (.Block simpleStorageNativeRetrieveBody) (some contract) - ((nativeSwitchPrefixFinalState contract tx storage observableSlots - (Backends.nativeSwitchDiscrTempName switchId) - (Backends.nativeSwitchMatchedTempName switchId)).insert - (Backends.nativeSwitchMatchedTempName switchId) - (EvmYul.UInt256.ofNat 1)) = - .error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) + EvmYul.Yul.exec ((fuel + 1) + suffix.length + 7) + (.Block simpleStorageNativeRetrieveBody) (some contract) + (nativeSwitchMarkedPrefixStateForId contract tx storage + observableSlots switchId) = + .error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) (hProject : projectResult tx storage initialEvents (.error (EvmYul.Yul.Exception.YulHalt haltState haltValue)) = @@ -14469,6 +34270,55 @@ def interpretRuntimeNative hLower, hEnv] rfl +@[simp] theorem interpretRuntimeNative_succ_eq_contractDispatcherBlockResult_of_lowerRuntimeContractNative + (fuel' : Nat) + (runtimeCode : List YulStmt) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (events : List (List Nat)) + (contract : EvmYul.Yul.Ast.YulContract) + (hFragment : generatedRuntimeNativeFragment runtimeCode = true) + (hLower : lowerRuntimeContractNative runtimeCode = .ok contract) + (hEnv : validateNativeRuntimeEnvironment runtimeCode tx = .ok ()) : + interpretRuntimeNative (Nat.succ fuel') runtimeCode tx storage observableSlots events = + .ok (projectResult tx storage events + (contractDispatcherBlockResult fuel' contract + (initialState contract tx storage + (materializedStorageSlots runtimeCode observableSlots)))) := by + rw [interpretRuntimeNative_eq_callDispatcher_of_lowerRuntimeContractNative + (fuel := Nat.succ fuel') (contract := contract) + (hFragment := hFragment) (hLower := hLower) (hEnv := hEnv)] + rw [callDispatcher_succ_eq_callDispatcherBlockResult] + rw [callDispatcherBlockResult_initialState_eq_contractDispatcherBlockResult] + +@[simp] theorem interpretRuntimeNative_succ_eq_contractDispatcherExecResult_of_lowerRuntimeContractNative + (fuel' : Nat) + (runtimeCode : List YulStmt) + (tx : YulTransaction) + (storage : IRStorageSlot → IRStorageWord) + (observableSlots : List Nat) + (events : List (List Nat)) + (contract : EvmYul.Yul.Ast.YulContract) + (hFragment : generatedRuntimeNativeFragment runtimeCode = true) + (hLower : lowerRuntimeContractNative runtimeCode = .ok contract) + (hEnv : validateNativeRuntimeEnvironment runtimeCode tx = .ok ()) : + interpretRuntimeNative (Nat.succ fuel') runtimeCode tx storage observableSlots events = + .ok (projectResult tx storage events + (let initial := + initialState contract tx storage + (materializedStorageSlots runtimeCode observableSlots) + let dispatcherDef := + EvmYul.Yul.Ast.FunctionDefinition.Def [] [] [contract.dispatcher] + match contractDispatcherExecResult fuel' contract initial with + | .error err => .error err + | .ok finalState => + let restored := finalState.reviveJump.overwrite? initial |>.setStore initial + .ok (restored, List.map finalState.lookup! dispatcherDef.rets))) := by + rw [interpretRuntimeNative_succ_eq_contractDispatcherBlockResult_of_lowerRuntimeContractNative + (contract := contract) (hFragment := hFragment) (hLower := hLower) (hEnv := hEnv)] + rw [contractDispatcherBlockResult_eq_execResult] + @[simp] theorem interpretRuntimeNative_environmentError (fuel : Nat) (runtimeCode : List YulStmt) @@ -14577,4 +34427,93 @@ def interpretIRRuntimeNative hFragment, hLower, hEnv] rfl +@[simp] theorem interpretIRRuntimeNative_succ_eq_contractDispatcherBlockResult_of_lowerRuntimeContractNative + (fuel' : Nat) + (irContract : Compiler.IRContract) + (tx : Compiler.Proofs.IRGeneration.IRTransaction) + (state : Compiler.Proofs.IRGeneration.IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (hFragment : + generatedRuntimeNativeFragment (Compiler.emitYul irContract).runtimeCode = true) + (hLower : lowerRuntimeContractNative (Compiler.emitYul irContract).runtimeCode = + .ok nativeContract) + (hEnv : + validateNativeRuntimeEnvironment (Compiler.emitYul irContract).runtimeCode + (YulTransaction.ofIR tx) = .ok ()) : + interpretIRRuntimeNative (Nat.succ fuel') irContract tx state observableSlots = + .ok (projectResult (YulTransaction.ofIR tx) state.storage state.events + (contractDispatcherBlockResult fuel' nativeContract + (initialState nativeContract (YulTransaction.ofIR tx) state.storage + (materializedStorageSlots (Compiler.emitYul irContract).runtimeCode + observableSlots)))) := by + rw [interpretIRRuntimeNative, interpretRuntimeNative_succ_eq_contractDispatcherBlockResult_of_lowerRuntimeContractNative + (contract := nativeContract) (hFragment := hFragment) (hLower := hLower) + (hEnv := hEnv)] + +@[simp] theorem interpretIRRuntimeNative_succ_eq_contractDispatcherExecResult_of_lowerRuntimeContractNative + (fuel' : Nat) + (irContract : Compiler.IRContract) + (tx : Compiler.Proofs.IRGeneration.IRTransaction) + (state : Compiler.Proofs.IRGeneration.IRState) + (observableSlots : List Nat) + (nativeContract : EvmYul.Yul.Ast.YulContract) + (hFragment : + generatedRuntimeNativeFragment (Compiler.emitYul irContract).runtimeCode = true) + (hLower : lowerRuntimeContractNative (Compiler.emitYul irContract).runtimeCode = + .ok nativeContract) + (hEnv : + validateNativeRuntimeEnvironment (Compiler.emitYul irContract).runtimeCode + (YulTransaction.ofIR tx) = .ok ()) : + interpretIRRuntimeNative (Nat.succ fuel') irContract tx state observableSlots = + .ok (projectResult (YulTransaction.ofIR tx) state.storage state.events + (let initial := + initialState nativeContract (YulTransaction.ofIR tx) state.storage + (materializedStorageSlots (Compiler.emitYul irContract).runtimeCode + observableSlots) + let dispatcherDef := + EvmYul.Yul.Ast.FunctionDefinition.Def [] [] [nativeContract.dispatcher] + match contractDispatcherExecResult fuel' nativeContract initial with + | .error err => .error err + | .ok finalState => + let restored := finalState.reviveJump.overwrite? initial |>.setStore initial + .ok (restored, List.map finalState.lookup! dispatcherDef.rets))) := by + rw [interpretIRRuntimeNative, interpretRuntimeNative_succ_eq_contractDispatcherExecResult_of_lowerRuntimeContractNative + (contract := nativeContract) (hFragment := hFragment) (hLower := hLower) + (hEnv := hEnv)] + +/-- Result comparison surface for the native EVMYulLean harness. + +The native harness can still fail closed during Verity-Yul-to-EVMYulLean +lowering, so native-facing theorem statements record both that native execution +returns a `YulResult` and that this result matches IR execution. -/ +private def nativeResultsMatch + (ir : IRResult) + (native : Except AdapterError YulResult) : + Prop := + match native with + | .ok yul => + ir.success = yul.success ∧ + ir.returnValue = yul.returnValue ∧ + (∀ slot, ir.finalStorage slot = yul.finalStorage slot) ∧ + (∀ base key, ir.finalMappings base key = yul.finalMappings base key) ∧ + ir.events = yul.events + | .error _ => False + +/-- Observable result comparison surface for native EVMYulLean execution. -/ +def nativeResultsMatchOn + (observableSlots : List Nat) + (ir : IRResult) + (native : Except AdapterError YulResult) : + Prop := + match native with + | .ok yul => + ir.success = yul.success ∧ + ir.returnValue = yul.returnValue ∧ + (∀ slot, slot ∈ observableSlots → + ir.finalStorage (IRStorageSlot.ofNat slot) = + yul.finalStorage (IRStorageSlot.ofNat slot)) ∧ + ir.events = yul.events + | .error _ => False + end Compiler.Proofs.YulGeneration.Backends.Native diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeSignedArithLemmas.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeSignedArithLemmas.lean new file mode 100644 index 000000000..eeba3eb5f --- /dev/null +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeSignedArithLemmas.lean @@ -0,0 +1,1318 @@ +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanAdapter +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanSignedArithSpec +import Mathlib.Data.Nat.Bitwise +import Verity.Core.Int256 +import Verity.Core.Uint256 + +namespace Compiler.Proofs.YulGeneration.Backends + +private theorem fin_val_mul_neg1 (n x : Nat) (hn : 0 < n) (hx : x < n) (hxpos : 0 < x) : + (x * (n - 1)) % n = n - x := by + have h1le : 1 ≤ n := hn + have hadd : x * (n - 1) + x = x * n := by + have : x * (n - 1) + x * 1 = x * n := by + rw [← Nat.left_distrib, Nat.sub_add_cancel h1le] + rwa [Nat.mul_one] at this + have h1lex : 1 ≤ x := hxpos + have hadd2 : (x - 1) * n + n = x * n := by + have : (x - 1) * n + 1 * n = x * n := by + rw [← Nat.right_distrib, Nat.sub_add_cancel h1lex] + rwa [Nat.one_mul] at this + have hdiv : x * (n - 1) = (x - 1) * n + (n - x) := by omega + rw [hdiv] + exact Nat.mul_add_mod_of_lt (by omega) + +private theorem natAbs_ofNat_sub (a b : Nat) (h : a < b) : + (Int.ofNat a - Int.ofNat b).natAbs = b - a := by + simp only [Int.ofNat_eq_coe] + rw [show (a : Int) - ((b : Nat) : Int) = -(((b : Nat) : Int) - (a : Int)) from by omega] + rw [Int.natAbs_neg] + rw [show ((b : Nat) : Int) - (a : Int) = ((b - a : Nat) : Int) from by omega] + simp only [Int.natAbs_natCast] + +set_option maxHeartbeats 400000000 in +set_option maxRecDepth 4096 in +theorem int256_div_toUint256_val_eq_uint256_sdiv (a b : Nat) + (ha : a < Compiler.Constants.evmModulus) (hb : b < Compiler.Constants.evmModulus) : + (Verity.Core.Int256.div + (Verity.Core.Int256.ofUint256 ⟨a, ha⟩) + (Verity.Core.Int256.ofUint256 ⟨b, hb⟩)).toUint256.val = + EvmYul.UInt256.toNat (EvmYul.UInt256.sdiv ⟨⟨a, by rw [EvmYul.UInt256.size]; exact ha⟩⟩ + ⟨⟨b, by rw [EvmYul.UInt256.size]; exact hb⟩⟩) := by + unfold Compiler.Constants.evmModulus at ha hb + by_cases hb0 : b = 0 + · subst hb0 + simp only [Verity.Core.Int256.div, Verity.Core.Int256.toInt, Verity.Core.Int256.ofUint256, + Verity.Core.Int256.signBit, Verity.Core.Int256.signedAbsNat, + Verity.Core.Int256.ofInt, Verity.Core.Int256.toUint256, + Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, Verity.Core.UINT256_MODULUS, + Verity.Core.Uint256.ofNat, + EvmYul.UInt256.sdiv, EvmYul.UInt256.abs, EvmYul.UInt256.toNat, + EvmYul.UInt256.size, + HDiv.hDiv, Div.div, EvmYul.UInt256.div, Fin.div] + simp only [show (0 : Nat) < 2^255 from by omega, + show ¬(2^255 ≤ (0:Nat)) from by omega, ↓reduceIte] + norm_num + conv_rhs => simp only [show ∀ (n : Nat), Nat.div n 0 = 0 from Nat.div_zero] + split <;> simp [Neg.neg] <;> decide + · by_cases haS : a < 2 ^ 255 <;> by_cases hbS : b < 2 ^ 255 + · simp only [Verity.Core.Int256.div, Verity.Core.Int256.toInt, Verity.Core.Int256.ofUint256, + Verity.Core.Int256.signBit, Verity.Core.Int256.signedAbsNat, + Verity.Core.Int256.ofInt, Verity.Core.Int256.toUint256, + Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, Verity.Core.UINT256_MODULUS, + Verity.Core.Uint256.ofNat, + EvmYul.UInt256.sdiv, EvmYul.UInt256.abs, EvmYul.UInt256.toNat, + EvmYul.UInt256.size] + simp only [eq_true haS, eq_true hbS, ↓reduceIte, + eq_false (show ¬(2^255 ≤ a) from by omega), + eq_false (show ¬(2^255 ≤ b) from by omega), + eq_false (show ¬((Int.ofNat b : Int) = 0) from Int.ofNat_ne_zero.mpr hb0), + eq_false (show ¬(Int.ofNat a < (0 : Int)) from not_lt.mpr (Int.natCast_nonneg a)), + eq_false (show ¬(Int.ofNat b < (0 : Int)) from not_lt.mpr (Int.natCast_nonneg b)), + decide_false] + simp only [BEq.beq, decide_true, ↓reduceIte] + simp only [Int.natAbs] + simp only [eq_false (show ¬(Int.ofNat (a / b) < (0 : Int)) from not_lt.mpr (Int.natCast_nonneg _)), + ↓reduceIte] + simp only [Int.toNat] + simp only [HDiv.hDiv, Div.div, EvmYul.UInt256.div, Fin.div] + exact Nat.mod_eq_of_lt (Nat.lt_of_le_of_lt (Nat.div_le_self a b) ha) + · have hb' : (Int.ofNat b : Int) < Int.ofNat (2^256) := Int.ofNat_lt.mpr hb + simp only [Verity.Core.Int256.div, Verity.Core.Int256.toInt, Verity.Core.Int256.ofUint256, + Verity.Core.Int256.signBit, Verity.Core.Int256.signedAbsNat, + Verity.Core.Int256.ofInt, Verity.Core.Int256.toUint256, + Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, Verity.Core.UINT256_MODULUS, + Verity.Core.Uint256.ofNat, + EvmYul.UInt256.sdiv, EvmYul.UInt256.abs, EvmYul.UInt256.toNat, + EvmYul.UInt256.size] + simp only [eq_true haS, eq_false hbS, + eq_false (show ¬(2^255 ≤ a) from by omega), + eq_true (show 2^255 ≤ b from by omega), ↓reduceIte, + eq_false (show ¬(Int.ofNat b - Int.ofNat (2^256) = (0 : Int)) from by omega), + eq_false (show ¬(Int.ofNat a < (0 : Int)) from not_lt.mpr (Int.natCast_nonneg a)), + eq_true (show Int.ofNat b - Int.ofNat (2^256) < (0 : Int) from by omega)] + simp only [BEq.beq, decide_false] + simp only [show (Int.ofNat a).natAbs = a from rfl, + natAbs_ofNat_sub b (2^256) hb] + simp only [HDiv.hDiv, Div.div, EvmYul.UInt256.div, Fin.div, Fin.mul] + norm_num + have habs_b_lit : b * 115792089237316195423570985008687907853269984665640564039457584007913129639935 % + 115792089237316195423570985008687907853269984665640564039457584007913129639936 = + 115792089237316195423570985008687907853269984665640564039457584007913129639936 - b := by + have := fin_val_mul_neg1 (2^256) b (by omega) hb (by omega) + norm_num at this; exact this + simp only [habs_b_lit] + simp only [Fin.val_neg] + split + · rename_i hqpos + have hqlt : a.div (115792089237316195423570985008687907853269984665640564039457584007913129639936 - b) < + 115792089237316195423570985008687907853269984665640564039457584007913129639936 := + Nat.lt_of_le_of_lt (Nat.div_le_self a _) ha + split + · rename_i h_fin_zero + exfalso; have hval := Fin.val_eq_of_eq h_fin_zero; simp at hval; omega + · show (115792089237316195423570985008687907853269984665640564039457584007913129639936 - + a.div (115792089237316195423570985008687907853269984665640564039457584007913129639936 - b) % + 115792089237316195423570985008687907853269984665640564039457584007913129639936) % + 115792089237316195423570985008687907853269984665640564039457584007913129639936 = + 115792089237316195423570985008687907853269984665640564039457584007913129639936 - + a.div (115792089237316195423570985008687907853269984665640564039457584007913129639936 - b) + rw [Nat.mod_eq_of_lt hqlt] + exact Nat.mod_eq_of_lt (by omega) + · rename_i hq0 + split + · rfl + · rename_i h_fin_ne; exfalso; apply h_fin_ne + have : a.div (115792089237316195423570985008687907853269984665640564039457584007913129639936 - b) = 0 := by omega + ext; simp [this] + · have ha' : (Int.ofNat a : Int) < Int.ofNat (2^256) := Int.ofNat_lt.mpr ha + simp only [Verity.Core.Int256.div, Verity.Core.Int256.toInt, Verity.Core.Int256.ofUint256, + Verity.Core.Int256.signBit, Verity.Core.Int256.signedAbsNat, + Verity.Core.Int256.ofInt, Verity.Core.Int256.toUint256, + Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, Verity.Core.UINT256_MODULUS, + Verity.Core.Uint256.ofNat, + EvmYul.UInt256.sdiv, EvmYul.UInt256.abs, EvmYul.UInt256.toNat, + EvmYul.UInt256.size] + simp only [eq_false haS, eq_true hbS, + eq_true (show 2^255 ≤ a from by omega), + eq_false (show ¬(2^255 ≤ b) from by omega), ↓reduceIte, + eq_true (show Int.ofNat a - Int.ofNat (2^256) < (0 : Int) from by omega), + eq_false (show ¬(Int.ofNat b < (0 : Int)) from not_lt.mpr (Int.natCast_nonneg b)), + eq_false (show ¬((Int.ofNat b : Int) = 0) from Int.ofNat_ne_zero.mpr hb0)] + simp only [BEq.beq, decide_false] + simp only [natAbs_ofNat_sub a (2^256) ha, + show (Int.ofNat b).natAbs = b from rfl] + simp only [HDiv.hDiv, Div.div, EvmYul.UInt256.div, Fin.div, Fin.mul] + norm_num + have habs_a_lit : a * 115792089237316195423570985008687907853269984665640564039457584007913129639935 % + 115792089237316195423570985008687907853269984665640564039457584007913129639936 = + 115792089237316195423570985008687907853269984665640564039457584007913129639936 - a := by + have := fin_val_mul_neg1 (2^256) a (by omega) ha (by omega) + norm_num at this; exact this + simp only [habs_a_lit] + simp only [Fin.val_neg] + split + · rename_i hqpos + have hqlt : (115792089237316195423570985008687907853269984665640564039457584007913129639936 - a).div b < + 115792089237316195423570985008687907853269984665640564039457584007913129639936 := + Nat.lt_of_le_of_lt (Nat.div_le_self _ _) (by omega) + split + · rename_i h_fin_zero + exfalso; have hval := Fin.val_eq_of_eq h_fin_zero; simp at hval; omega + · show (115792089237316195423570985008687907853269984665640564039457584007913129639936 - + (115792089237316195423570985008687907853269984665640564039457584007913129639936 - a).div b % + 115792089237316195423570985008687907853269984665640564039457584007913129639936) % + 115792089237316195423570985008687907853269984665640564039457584007913129639936 = + 115792089237316195423570985008687907853269984665640564039457584007913129639936 - + (115792089237316195423570985008687907853269984665640564039457584007913129639936 - a).div b + rw [Nat.mod_eq_of_lt hqlt] + exact Nat.mod_eq_of_lt (by omega) + · rename_i hq0 + split + · rfl + · rename_i h_fin_ne; exfalso; apply h_fin_ne + have : (115792089237316195423570985008687907853269984665640564039457584007913129639936 - a).div b = 0 := by omega + ext; simp [this] + · have ha' : (Int.ofNat a : Int) < Int.ofNat (2^256) := Int.ofNat_lt.mpr ha + have hb' : (Int.ofNat b : Int) < Int.ofNat (2^256) := Int.ofNat_lt.mpr hb + simp only [Verity.Core.Int256.div, Verity.Core.Int256.toInt, Verity.Core.Int256.ofUint256, + Verity.Core.Int256.signBit, Verity.Core.Int256.signedAbsNat, + Verity.Core.Int256.ofInt, Verity.Core.Int256.toUint256, + Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, Verity.Core.UINT256_MODULUS, + Verity.Core.Uint256.ofNat, + EvmYul.UInt256.sdiv, EvmYul.UInt256.abs, EvmYul.UInt256.toNat, + EvmYul.UInt256.size] + simp only [eq_false haS, eq_false hbS, + eq_true (show 2^255 ≤ a from by omega), + eq_true (show 2^255 ≤ b from by omega), ↓reduceIte, + eq_false (show ¬(Int.ofNat b - Int.ofNat (2^256) = (0 : Int)) from by omega), + eq_true (show Int.ofNat a - Int.ofNat (2^256) < (0 : Int) from by omega), + eq_true (show Int.ofNat b - Int.ofNat (2^256) < (0 : Int) from by omega)] + simp only [BEq.beq] + simp only [natAbs_ofNat_sub a (2^256) ha, + natAbs_ofNat_sub b (2^256) hb] + simp only [decide_true, ↓reduceIte, + eq_false (show ¬(Int.ofNat ((2^256 - a) / (2^256 - b)) < (0 : Int)) from + not_lt.mpr (Int.natCast_nonneg _))] + simp only [Int.toNat] + simp only [HDiv.hDiv, Div.div, EvmYul.UInt256.div, Fin.div, Fin.mul] + norm_num + rw [fin_val_mul_neg1 (2^256) a (by omega) ha (by omega), + fin_val_mul_neg1 (2^256) b (by omega) hb (by omega)] + exact Nat.mod_eq_of_lt (Nat.lt_of_le_of_lt (Nat.div_le_self _ _) (by omega)) + +private theorem eq0_true_of_val_eq_zero (x : EvmYul.UInt256) (h : x.val = 0) : + EvmYul.UInt256.eq0 x = true := by + have hx : x = ⟨0⟩ := by cases x; exact congrArg EvmYul.UInt256.mk h + subst hx; decide + +private theorem eq0_false_of_val_ne_zero (x : EvmYul.UInt256) (h : x.val ≠ 0) : + EvmYul.UInt256.eq0 x = false := by + cases hb : EvmYul.UInt256.eq0 x with + | false => rfl + | true => + exfalso; apply h + cases x with | mk v => + simp only [EvmYul.UInt256.eq0] at hb + change (v == (0 : Fin EvmYul.UInt256.size)) = true at hb + have hv : v = (0 : Fin EvmYul.UInt256.size) := of_decide_eq_true hb + simp [hv] + +private theorem int256_ofInt_nat_toUint256_val (r : Nat) (hr : r < Compiler.Constants.evmModulus) : + (Verity.Core.Int256.ofInt (Int.ofNat r)).toUint256.val = r := by + simp [Verity.Core.Int256.ofInt, Verity.Core.Int256.toUint256, + Verity.Core.Uint256.ofNat, Verity.Core.Uint256.modulus, Verity.Core.UINT256_MODULUS] + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using hr) + +/-- Negative-wrapper counterpart to `int256_ofInt_nat_toUint256_val` used by + the NP/NN sign cases of the `smod` core equivalence: + `(Verity.Core.Int256.ofInt (-Int.ofNat r)).toUint256.val = + if r = 0 then 0 else Compiler.Constants.evmModulus - r`. -/ +private theorem int256_ofInt_neg_nat_toUint256_val (r : Nat) (hr : r < Compiler.Constants.evmModulus) : + (Verity.Core.Int256.ofInt (-Int.ofNat r)).toUint256.val = + if r = 0 then 0 else Compiler.Constants.evmModulus - r := by + by_cases hr0 : r = 0 + · subst hr0 + simp [Verity.Core.Int256.ofInt, Verity.Core.Int256.toUint256, + Verity.Core.Int256.ofUint256, Verity.Core.Uint256.ofNat] + · have hrpos : 0 < r := Nat.pos_of_ne_zero hr0 + have hneg : (-Int.ofNat r : Int) < 0 := by + have : (0 : Int) < Int.ofNat r := Int.natCast_pos.mpr hrpos + omega + have hnatAbs : Int.natAbs (-Int.ofNat r) = r := by + simp [Int.natAbs_neg] + have hmod_eq : Verity.Core.Int256.modulus = Compiler.Constants.evmModulus := by + simp [Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, + Verity.Core.UINT256_MODULUS, Compiler.Constants.evmModulus] + have hr_lt_mod : r < Verity.Core.Int256.modulus := by rw [hmod_eq]; exact hr + have hmod_r : r % Verity.Core.Int256.modulus = r := Nat.mod_eq_of_lt hr_lt_mod + have hsub_lt : Verity.Core.Int256.modulus - r < Verity.Core.Int256.modulus := by + have : 0 < Verity.Core.Int256.modulus := by rw [hmod_eq]; unfold Compiler.Constants.evmModulus; omega + omega + rw [if_neg hr0] + simp only [Verity.Core.Int256.ofInt, if_pos hneg, + Verity.Core.Int256.toUint256, Verity.Core.Int256.ofUint256, + Verity.Core.Uint256.ofNat, hnatAbs, hmod_r] + show (Verity.Core.Int256.modulus - r) % Verity.Core.Uint256.modulus = Compiler.Constants.evmModulus - r + have hmod_eq' : Verity.Core.Int256.modulus = Verity.Core.Uint256.modulus := rfl + rw [hmod_eq', Nat.mod_eq_of_lt (by rw [← hmod_eq']; exact hsub_lt)] + show Verity.Core.Uint256.modulus - r = Compiler.Constants.evmModulus - r + rw [hmod_eq.symm.trans hmod_eq'] + +/-! ### Verity-side reduction for A2 + +The next three lemmas reduce Verity's `Int256.signedAbsNat ∘ toInt` on a +word to the Nat-level `SignedArithSpec.specAbs`, and reduce the sign +tests on `(ofUint256 ⟨n, _⟩ : Int)` to comparisons on `n`. They compose +into `int256_mod_toUint256_val_eq_smodSpec`, which is the Verity-side +half of the `smod` core equivalence (A2). -/ + +private theorem int256_ofUint256_coe_eq (a : Nat) (ha : a < Compiler.Constants.evmModulus) : + ((Verity.Core.Int256.ofUint256 ⟨a, ha⟩ : Verity.Core.Int256) : Int) = + if a < SignedArithSpec.specSignBit then Int.ofNat a + else Int.ofNat a - Int.ofNat Verity.Core.Int256.modulus := by + show Verity.Core.Int256.toInt _ = _ + unfold Verity.Core.Int256.toInt + have hword : (Verity.Core.Int256.ofUint256 ⟨a, ha⟩ : Verity.Core.Int256).word.val = a := rfl + have hSB : SignedArithSpec.specSignBit = Verity.Core.Int256.signBit := rfl + rw [hword, hSB] + +private theorem evmModulus_eq_specModulus : Compiler.Constants.evmModulus = SignedArithSpec.specModulus := rfl + +private theorem int256_modulus_eq_specModulus : + Verity.Core.Int256.modulus = SignedArithSpec.specModulus := by + simp [Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, + Verity.Core.UINT256_MODULUS, SignedArithSpec.specModulus] + +private theorem signedAbsNat_of_ofUint256 (a : Nat) (ha : a < Compiler.Constants.evmModulus) : + Verity.Core.Int256.signedAbsNat + ((Verity.Core.Int256.ofUint256 ⟨a, ha⟩ : Verity.Core.Int256) : Int) = + SignedArithSpec.specAbs a := by + unfold Verity.Core.Int256.signedAbsNat SignedArithSpec.specAbs + rw [int256_ofUint256_coe_eq a ha] + have hMod : Verity.Core.Int256.modulus = Compiler.Constants.evmModulus := by + simp [Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, + Verity.Core.UINT256_MODULUS, Compiler.Constants.evmModulus] + by_cases hS : a < SignedArithSpec.specSignBit + · rw [if_pos hS, if_pos hS] + show (Int.ofNat a).natAbs = a + rfl + · rw [if_neg hS, if_neg hS] + have ha' : a < Verity.Core.Int256.modulus := by rw [hMod]; exact ha + have hle : a ≤ Verity.Core.Int256.modulus := Nat.le_of_lt ha' + have hcast : (Int.ofNat (Verity.Core.Int256.modulus - a) : Int) = + Int.ofNat Verity.Core.Int256.modulus - Int.ofNat a := + Int.ofNat_sub hle + have hsub : Int.ofNat a - Int.ofNat Verity.Core.Int256.modulus = + -(Int.ofNat (Verity.Core.Int256.modulus - a)) := by + rw [hcast]; ring + rw [hsub, Int.natAbs_neg] + show Verity.Core.Int256.modulus - a = SignedArithSpec.specModulus - a + rw [int256_modulus_eq_specModulus] + +private theorem int256_coe_lt_zero_iff (a : Nat) (ha : a < Compiler.Constants.evmModulus) : + ((Verity.Core.Int256.ofUint256 ⟨a, ha⟩ : Verity.Core.Int256) : Int) < 0 ↔ + SignedArithSpec.specSignBit ≤ a := by + rw [int256_ofUint256_coe_eq a ha] + have hMod : Verity.Core.Int256.modulus = Compiler.Constants.evmModulus := by + simp [Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, + Verity.Core.UINT256_MODULUS, Compiler.Constants.evmModulus] + have ha' : a < Verity.Core.Int256.modulus := by rw [hMod]; exact ha + by_cases hS : a < SignedArithSpec.specSignBit + · rw [if_pos hS] + have hnn : (0 : Int) ≤ Int.ofNat a := Int.natCast_nonneg a + constructor + · intro h; omega + · intro h; exact absurd h (Nat.not_le.mpr hS) + · rw [if_neg hS] + have hge : SignedArithSpec.specSignBit ≤ a := Nat.le_of_not_lt hS + have hlt_int : Int.ofNat a < Int.ofNat Verity.Core.Int256.modulus := Int.ofNat_lt.mpr ha' + constructor + · intro _; exact hge + · intro _; omega + +private theorem int256_coe_eq_zero_iff (a : Nat) (ha : a < Compiler.Constants.evmModulus) : + ((Verity.Core.Int256.ofUint256 ⟨a, ha⟩ : Verity.Core.Int256) : Int) = 0 ↔ + a = 0 := by + rw [int256_ofUint256_coe_eq a ha] + have hMod : Verity.Core.Int256.modulus = Compiler.Constants.evmModulus := by + simp [Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, + Verity.Core.UINT256_MODULUS, Compiler.Constants.evmModulus] + have ha' : a < Verity.Core.Int256.modulus := by rw [hMod]; exact ha + by_cases hS : a < SignedArithSpec.specSignBit + · rw [if_pos hS]; exact Int.ofNat_eq_zero + · rw [if_neg hS] + have hge : SignedArithSpec.specSignBit ≤ a := Nat.le_of_not_lt hS + have hSBpos : 0 < SignedArithSpec.specSignBit := SignedArithSpec.specSignBit_pos + constructor + · intro h + have : Int.ofNat a < Int.ofNat Verity.Core.Int256.modulus := Int.ofNat_lt.mpr ha' + omega + · intro h; subst h; exact absurd hge (Nat.not_le.mpr hSBpos) + +/-- Verity-side half of A2: `Int256.mod`'s `.toUint256.val` view +reduces exactly to `smodSpec` at the Nat level. Composes +`int256_ofInt_nat_toUint256_val` / `int256_ofInt_neg_nat_toUint256_val` +for the non-negative/negative `a` sign cases with the sign-case +characterizations `smodSpec_of_nonneg` / `smodSpec_of_neg`. -/ +private theorem int256_mod_toUint256_val_eq_smodSpec (a b : Nat) + (ha : a < Compiler.Constants.evmModulus) (hb : b < Compiler.Constants.evmModulus) : + (Verity.Core.Int256.mod + (Verity.Core.Int256.ofUint256 ⟨a, ha⟩) + (Verity.Core.Int256.ofUint256 ⟨b, hb⟩)).toUint256.val = + SignedArithSpec.smodSpec a b := by + unfold Verity.Core.Int256.mod + have habs_a := signedAbsNat_of_ofUint256 a ha + have habs_b := signedAbsNat_of_ofUint256 b hb + have hzero_b := int256_coe_eq_zero_iff b hb + have hneg_a := int256_coe_lt_zero_iff a ha + by_cases hb0 : b = 0 + · -- b = 0 branch on both sides + subst hb0 + simp only [hzero_b.mpr rfl, if_true] + show ((0 : Verity.Core.Int256) : Verity.Core.Uint256).val = _ + rw [SignedArithSpec.smodSpec_b_zero] + rfl + · -- b ≠ 0 + have hrhs_ne : ((Verity.Core.Int256.ofUint256 ⟨b, hb⟩ : Verity.Core.Int256) : Int) ≠ 0 := by + intro h; exact hb0 (hzero_b.mp h) + simp only [hrhs_ne, if_false] + have habs_b_pos : 0 < SignedArithSpec.specAbs b := by + unfold SignedArithSpec.specAbs + by_cases hbs : b < SignedArithSpec.specSignBit + · simp [hbs]; exact Nat.pos_of_ne_zero hb0 + · simp [hbs] + have hb_ge : SignedArithSpec.specSignBit ≤ b := Nat.le_of_not_lt hbs + have hmod := SignedArithSpec.specModulus_pos + have hSBlt := SignedArithSpec.specSignBit_lt_specModulus + have hbmod : b < SignedArithSpec.specModulus := by + show b < 2^256 + exact hb + omega + have hr_lt_specAbsB : SignedArithSpec.specAbs a % SignedArithSpec.specAbs b < SignedArithSpec.specAbs b := + Nat.mod_lt _ habs_b_pos + have habs_b_le : SignedArithSpec.specAbs b ≤ SignedArithSpec.specSignBit := + SignedArithSpec.specAbs_le_specSignBit b + have hSBlt : SignedArithSpec.specSignBit < SignedArithSpec.specModulus := + SignedArithSpec.specSignBit_lt_specModulus + have hr_lt_mod : SignedArithSpec.specAbs a % SignedArithSpec.specAbs b < Compiler.Constants.evmModulus := by + have : SignedArithSpec.specAbs a % SignedArithSpec.specAbs b < SignedArithSpec.specModulus := by + omega + exact this + rw [habs_a, habs_b] + by_cases haS : a < SignedArithSpec.specSignBit + · -- non-negative a + have hnlt : ¬ ((Verity.Core.Int256.ofUint256 ⟨a, ha⟩ : Verity.Core.Int256) : Int) < 0 := by + rw [hneg_a]; exact Nat.not_le.mpr haS + simp only [hnlt, if_false] + rw [int256_ofInt_nat_toUint256_val _ hr_lt_mod] + rw [SignedArithSpec.smodSpec_of_nonneg a b haS hb0] + · -- negative a + have hge : SignedArithSpec.specSignBit ≤ a := Nat.le_of_not_lt haS + have hlt : ((Verity.Core.Int256.ofUint256 ⟨a, ha⟩ : Verity.Core.Int256) : Int) < 0 := by + rw [hneg_a]; exact hge + simp only [hlt, if_true] + rw [int256_ofInt_neg_nat_toUint256_val _ hr_lt_mod] + rw [SignedArithSpec.smodSpec_of_neg a b hge hb0] + rw [evmModulus_eq_specModulus] + +/-! ### EVMYulLean-side abs reduction for A2 + +Mirror of the Verity-side `signedAbsNat_of_ofUint256` helper: reduces +`EvmYul.UInt256.abs` on a raw-Nat word to `SignedArithSpec.specAbs`. The +negative branch applies `fin_val_mul_neg1` to collapse Fin-multiplication +by `-1` into two's-complement subtraction. Future A2b work can compose +this with `smodSpec_of_nonneg`/`_of_neg` + `toSigned` characterizations to +close the EVMYulLean side of the `smod` core equivalence, symmetric to +`int256_mod_toUint256_val_eq_smodSpec` on the Verity side. -/ +private theorem uint256_abs_toNat_eq_specAbs (a : Nat) (ha : a < Compiler.Constants.evmModulus) : + EvmYul.UInt256.toNat + (EvmYul.UInt256.abs ⟨⟨a, by rw [EvmYul.UInt256.size]; exact ha⟩⟩) = + SignedArithSpec.specAbs a := by + unfold Compiler.Constants.evmModulus at ha + unfold EvmYul.UInt256.abs EvmYul.UInt256.toNat SignedArithSpec.specAbs + by_cases haS : a < SignedArithSpec.specSignBit + · -- Non-negative branch: abs returns the value unchanged, specAbs returns `a`. + have hnot : ¬ (2^255 ≤ a) := by + have : a < 2^255 := haS + omega + show (if 2^255 ≤ a then _ else (⟨⟨a, _⟩⟩ : EvmYul.UInt256)).val.val = + if a < SignedArithSpec.specSignBit then a else SignedArithSpec.specModulus - a + rw [if_neg hnot, if_pos haS] + · -- Negative branch: abs returns `⟨a.val * (-1)⟩`; specAbs returns `specModulus - a`. + have hge : 2^255 ≤ a := by + have hnot : ¬ a < SignedArithSpec.specSignBit := haS + have : SignedArithSpec.specSignBit = 2^255 := rfl + omega + have hpos : 0 < a := by + have h255 : 0 < (2 : Nat)^255 := by positivity + omega + show (if 2^255 ≤ a then (⟨⟨a, _⟩ * (-1 : Fin EvmYul.UInt256.size)⟩ : EvmYul.UInt256) + else _).val.val = + if a < SignedArithSpec.specSignBit then a else SignedArithSpec.specModulus - a + rw [if_pos hge, if_neg haS] + show ((⟨a, _⟩ : Fin EvmYul.UInt256.size) * (-1 : Fin EvmYul.UInt256.size)).val = + SignedArithSpec.specModulus - a + simp only [EvmYul.UInt256.size] + norm_num + simp only [Fin.val_neg] + norm_num + -- After simp + norm_num, the goal reduces to + -- `(if a = 0 then 0 else 115792... - a) = SignedArithSpec.specModulus - a`. + -- `hpos : 0 < a` discharges the `a = 0` branch, and the literal is + -- definitionally `specModulus`. + have ha0 : a ≠ 0 := Nat.pos_iff_ne_zero.mp hpos + rw [if_neg ha0] + rfl + +/-! ### EVMYulLean-side mod reduction to Nat-level mod (for A2b) + +Reduces `(a % b : UInt256).toNat` to `a.toNat % b.toNat` under the nonzero +hypothesis on `b` (the zero branch forces a `0` result on the UInt256 side +but yields `a` on the Nat side, so the conditional is necessary). This is +the straightforward `Fin.mod` unfolding needed to let the A2b composition +push `UInt256.mod` through to `Nat.mod`. -/ +private theorem uint256_mod_toNat_of_nonzero + (a b : EvmYul.UInt256) (hb : EvmYul.UInt256.toNat b ≠ 0) : + EvmYul.UInt256.toNat (a % b) = + EvmYul.UInt256.toNat a % EvmYul.UInt256.toNat b := by + show EvmYul.UInt256.toNat (EvmYul.UInt256.mod a b) = _ + unfold EvmYul.UInt256.mod EvmYul.UInt256.toNat + split_ifs with h + · exfalso + apply hb + simp only [beq_iff_eq] at h + show b.val.val = 0 + rw [h]; rfl + · rfl + +/-! ### EVMYulLean toSigned characterizations (A2b scaffolds) + +Splits `toNat ∘ toSigned` by the `Int` constructor. `toSigned` is defined on +the Verity side as +``` +match i with + | .ofNat n => ofNat n + | .negSucc n => ofNat (UInt256.size - 1 - n) +``` +so `toNat` reduces to `n % size` and `(size - 1 - n) % size` respectively. +Bounded inputs remove the modulus, which is what A2b's case split needs. -/ +private theorem uint256_toSigned_ofNat_toNat_of_lt + (n : Nat) (hn : n < EvmYul.UInt256.size) : + EvmYul.UInt256.toNat (EvmYul.UInt256.toSigned (Int.ofNat n)) = n := by + show EvmYul.UInt256.toNat (EvmYul.UInt256.ofNat n) = n + unfold EvmYul.UInt256.ofNat EvmYul.UInt256.toNat + simp only [Id.run] + show (Fin.ofNat EvmYul.UInt256.size n).val = n + unfold Fin.ofNat + exact Nat.mod_eq_of_lt hn + +private theorem uint256_toSigned_negSucc_toNat_of_lt + (n : Nat) (hn : n + 1 < EvmYul.UInt256.size) : + EvmYul.UInt256.toNat (EvmYul.UInt256.toSigned (Int.negSucc n)) = + EvmYul.UInt256.size - 1 - n := by + show EvmYul.UInt256.toNat (EvmYul.UInt256.ofNat (EvmYul.UInt256.size - 1 - n)) = _ + unfold EvmYul.UInt256.ofNat EvmYul.UInt256.toNat + simp only [Id.run] + show (Fin.ofNat EvmYul.UInt256.size (EvmYul.UInt256.size - 1 - n)).val = + EvmYul.UInt256.size - 1 - n + unfold Fin.ofNat + have h : EvmYul.UInt256.size - 1 - n < EvmYul.UInt256.size := by + have hpos : 0 < EvmYul.UInt256.size := by + unfold EvmYul.UInt256.size; decide + omega + exact Nat.mod_eq_of_lt h + +/-! ### EVMYulLean-side smod reduction to smodSpec (A2c) + +Symmetric to `int256_mod_toUint256_val_eq_smodSpec`: reduces +`toNat (UInt256.smod a b)` to `SignedArithSpec.smodSpec a.toNat b.toNat`. + +The EVMYulLean definition is +``` +smod a b = if b.toNat == 0 then ⟨0⟩ + else toSigned (sgn a * (abs a % abs b).toNat) +``` +Each branch is discharged by composing the previously-landed scaffolds: + +* Zero-divisor: direct from `smodSpec_b_zero`. +* Non-negative `a` (`a < specSignBit`), `a = 0`: `sgn = 0`, product `= 0 = Int.ofNat 0`, `toSigned` gives `0`; `smodSpec_a_zero` gives `0`. +* Non-negative `a`, `a ≠ 0`: `sgn = 1`, product `= Int.ofNat r` with `r < specSignBit < size`; `toSigned` collapses via `uint256_toSigned_ofNat_toNat_of_lt`; RHS matches `smodSpec_of_nonneg`. +* Negative `a` (`specSignBit ≤ a`), `r = 0`: `sgn * 0 = 0`; `toSigned 0 = 0`; RHS matches `smodSpec_of_neg` at its `r = 0` branch. +* Negative `a`, `r > 0`: `sgn * r = -r = Int.negSucc (r-1)`; `toSigned` collapses via `uint256_toSigned_negSucc_toNat_of_lt` to `size - r = specModulus - r`; RHS matches `smodSpec_of_neg`. +-/ +private theorem uint256_smod_toNat_eq_smodSpec (a b : Nat) + (ha : a < Compiler.Constants.evmModulus) (hb : b < Compiler.Constants.evmModulus) : + EvmYul.UInt256.toNat + (EvmYul.UInt256.smod ⟨⟨a, by rw [EvmYul.UInt256.size]; exact ha⟩⟩ + ⟨⟨b, by rw [EvmYul.UInt256.size]; exact hb⟩⟩) = + SignedArithSpec.smodSpec a b := by + -- Size bounds + have hsize_a : a < EvmYul.UInt256.size := by rw [EvmYul.UInt256.size]; exact ha + have hsize_b : b < EvmYul.UInt256.size := by rw [EvmYul.UInt256.size]; exact hb + -- Working abbreviations + let ua : EvmYul.UInt256 := ⟨⟨a, hsize_a⟩⟩ + let ub : EvmYul.UInt256 := ⟨⟨b, hsize_b⟩⟩ + have hua_toNat : EvmYul.UInt256.toNat ua = a := rfl + have hub_toNat : EvmYul.UInt256.toNat ub = b := rfl + -- Zero-divisor split + by_cases hb0 : b = 0 + · subst hb0 + rw [SignedArithSpec.smodSpec_b_zero] + show EvmYul.UInt256.toNat (EvmYul.UInt256.smod ua ub) = 0 + unfold EvmYul.UInt256.smod + have h_beq : (EvmYul.UInt256.toNat ub == 0) = true := by + rw [hub_toNat]; rfl + rw [h_beq] + rfl + · -- b ≠ 0 + show EvmYul.UInt256.toNat (EvmYul.UInt256.smod ua ub) = SignedArithSpec.smodSpec a b + unfold EvmYul.UInt256.smod + have h_beq : (EvmYul.UInt256.toNat ub == 0) = false := by + rw [hub_toNat] + simp [hb0] + rw [h_beq] + simp only [Bool.false_eq_true, ↓reduceIte] + -- Goal: toNat (toSigned (sgn ua * ↑(toNat (abs ua % abs ub)))) = smodSpec a b + -- Reduce abs operations + have habs_ua_toNat : EvmYul.UInt256.toNat (EvmYul.UInt256.abs ua) = SignedArithSpec.specAbs a := + uint256_abs_toNat_eq_specAbs a ha + have habs_ub_toNat : EvmYul.UInt256.toNat (EvmYul.UInt256.abs ub) = SignedArithSpec.specAbs b := + uint256_abs_toNat_eq_specAbs b hb + -- specAbs b is nonzero + have habs_b_ne : SignedArithSpec.specAbs b ≠ 0 := by + unfold SignedArithSpec.specAbs + by_cases hbs : b < SignedArithSpec.specSignBit + · simp [hbs]; exact hb0 + · simp [hbs] + have hbmod : b < SignedArithSpec.specModulus := by + show b < 2^256 + exact hb + omega + have habs_b_pos : 0 < SignedArithSpec.specAbs b := Nat.pos_of_ne_zero habs_b_ne + have habs_ub_ne : EvmYul.UInt256.toNat (EvmYul.UInt256.abs ub) ≠ 0 := by + rw [habs_ub_toNat]; exact habs_b_ne + -- Reduce abs % abs via uint256_mod_toNat_of_nonzero + have hmod_toNat : + EvmYul.UInt256.toNat (EvmYul.UInt256.abs ua % EvmYul.UInt256.abs ub) = + SignedArithSpec.specAbs a % SignedArithSpec.specAbs b := by + rw [uint256_mod_toNat_of_nonzero _ _ habs_ub_ne, habs_ua_toNat, habs_ub_toNat] + -- Let r := specAbs a % specAbs b + set r : Nat := SignedArithSpec.specAbs a % SignedArithSpec.specAbs b with hr_def + -- r bounds + have hr_lt_absB : r < SignedArithSpec.specAbs b := Nat.mod_lt _ habs_b_pos + have habs_b_le : SignedArithSpec.specAbs b ≤ SignedArithSpec.specSignBit := + SignedArithSpec.specAbs_le_specSignBit b + have hSB_lt_size : SignedArithSpec.specSignBit < EvmYul.UInt256.size := by + show (2:Nat)^255 < 2^256; decide + have hr_lt_size : r < EvmYul.UInt256.size := by + have hr_le_SB : r < SignedArithSpec.specSignBit := by omega + omega + have hr_lt_SB : r < SignedArithSpec.specSignBit := by omega + -- Case split on sgn a (non-negative vs negative) + unfold EvmYul.UInt256.sgn + by_cases haS : a < SignedArithSpec.specSignBit + · -- Non-negative a: 2^255 ≤ a is false + have h_not_neg : ¬ (2:Nat)^255 ≤ EvmYul.UInt256.toNat ua := by + rw [hua_toNat] + have : a < (2:Nat)^255 := haS + omega + simp only [h_not_neg, ↓reduceIte] + by_cases ha0 : a = 0 + · -- a = 0: eq0 ua = true, sgn = 0 + have hua_val : ua.val = 0 := by + show (⟨a, hsize_a⟩ : Fin EvmYul.UInt256.size) = 0 + apply Fin.ext + show a = 0 + exact ha0 + have h_eq0 : EvmYul.UInt256.eq0 ua = true := eq0_true_of_val_eq_zero ua hua_val + simp only [h_eq0] + -- sgn = 0 → 0 * _ = 0 = Int.ofNat 0 + show EvmYul.UInt256.toNat + (EvmYul.UInt256.toSigned + ((0 : Int) * ((EvmYul.UInt256.toNat + (EvmYul.UInt256.abs ua % EvmYul.UInt256.abs ub)) : Int))) = + SignedArithSpec.smodSpec a b + rw [zero_mul] + rw [show (0 : Int) = Int.ofNat 0 from rfl] + rw [uint256_toSigned_ofNat_toNat_of_lt 0 + (by unfold EvmYul.UInt256.size; decide)] + -- RHS: smodSpec 0 b = 0 + subst ha0 + rw [SignedArithSpec.smodSpec_a_zero] + · -- a ≠ 0: eq0 ua = false, sgn = 1 + have hua_val_ne : ua.val ≠ 0 := by + intro h + apply ha0 + show a = 0 + exact congrArg Fin.val h + have h_eq0 : EvmYul.UInt256.eq0 ua = false := eq0_false_of_val_ne_zero ua hua_val_ne + simp only [h_eq0] + -- sgn = 1 → 1 * ↑r = ↑r = Int.ofNat r + show EvmYul.UInt256.toNat + (EvmYul.UInt256.toSigned + ((1 : Int) * ((EvmYul.UInt256.toNat + (EvmYul.UInt256.abs ua % EvmYul.UInt256.abs ub)) : Int))) = + SignedArithSpec.smodSpec a b + rw [one_mul, hmod_toNat] + rw [show ((r : Int)) = Int.ofNat r from rfl] + rw [uint256_toSigned_ofNat_toNat_of_lt r hr_lt_size] + rw [SignedArithSpec.smodSpec_of_nonneg a b haS hb0] + · -- Negative a: 2^255 ≤ a + have hge : SignedArithSpec.specSignBit ≤ a := Nat.le_of_not_lt haS + have h_is_neg : (2:Nat)^255 ≤ EvmYul.UInt256.toNat ua := by + rw [hua_toNat] + exact hge + simp only [h_is_neg, ↓reduceIte] + -- sgn = -1 → -1 * ↑r + show EvmYul.UInt256.toNat + (EvmYul.UInt256.toSigned + ((-1 : Int) * ((EvmYul.UInt256.toNat + (EvmYul.UInt256.abs ua % EvmYul.UInt256.abs ub)) : Int))) = + SignedArithSpec.smodSpec a b + rw [hmod_toNat] + rw [SignedArithSpec.smodSpec_of_neg a b hge hb0] + by_cases hr0 : r = 0 + · -- r = 0 + rw [hr0] + simp only [Int.natCast_zero, mul_zero] + rw [show (0 : Int) = Int.ofNat 0 from rfl] + rw [uint256_toSigned_ofNat_toNat_of_lt 0 (by unfold EvmYul.UInt256.size; decide)] + have hr0spec : SignedArithSpec.specAbs a % SignedArithSpec.specAbs b = 0 := by + rw [← hr_def] + exact hr0 + rw [if_pos hr0spec] + · -- r > 0 + have hr_pos : 0 < r := Nat.pos_of_ne_zero hr0 + -- -1 * ↑r = Int.negSucc (r - 1) + have hprod : (-1 : Int) * (r : Int) = Int.negSucc (r - 1) := by + cases h : r with + | zero => exact False.elim (hr0 h) + | succ k => + simp [Int.negSucc_eq] + rw [hprod] + have hr_bound : (r - 1) + 1 < EvmYul.UInt256.size := by omega + rw [uint256_toSigned_negSucc_toNat_of_lt (r - 1) hr_bound] + -- Goal: size - 1 - (r-1) = if r = 0 then 0 else specModulus - r + rw [if_neg hr0] + show EvmYul.UInt256.size - 1 - (r - 1) = SignedArithSpec.specModulus - r + have hr_pos : 0 < r := Nat.pos_of_ne_zero hr0 + have h_eq : EvmYul.UInt256.size = SignedArithSpec.specModulus := rfl + rw [h_eq] + omega + +/-- Core smod equivalence: Verity's `Int256.mod` agrees with EVMYulLean's `UInt256.smod`. + +**Closed via A2a + A2c**: Verity-side reduction +`int256_mod_toUint256_val_eq_smodSpec` and EVMYulLean-side reduction +`uint256_smod_toNat_eq_smodSpec` both go through the shared +`SignedArithSpec.smodSpec`, and the composition discharges the wrapper. -/ +theorem int256_mod_toUint256_val_eq_uint256_smod (a b : Nat) + (ha : a < Compiler.Constants.evmModulus) (hb : b < Compiler.Constants.evmModulus) : + (Verity.Core.Int256.mod + (Verity.Core.Int256.ofUint256 ⟨a, ha⟩) + (Verity.Core.Int256.ofUint256 ⟨b, hb⟩)).toUint256.val = + EvmYul.UInt256.toNat (EvmYul.UInt256.smod ⟨⟨a, by rw [EvmYul.UInt256.size]; exact ha⟩⟩ + ⟨⟨b, by rw [EvmYul.UInt256.size]; exact hb⟩⟩) := by + rw [int256_mod_toUint256_val_eq_smodSpec a b ha hb] + rw [uint256_smod_toNat_eq_smodSpec a b ha hb] + +private theorem uint256_lt_zero_false (value : Nat) (hv : value < EvmYul.UInt256.size) : + ¬ ((⟨⟨value, hv⟩⟩ : EvmYul.UInt256) < ⟨0⟩) := by + intro h + change (⟨value, hv⟩ : Fin EvmYul.UInt256.size) < (0 : Fin EvmYul.UInt256.size) at h + exact Nat.not_lt_zero _ h + +private theorem uint256_complement_val (value : Nat) (hv : value < EvmYul.UInt256.size) : + EvmYul.UInt256.toNat (EvmYul.UInt256.complement ⟨⟨value, hv⟩⟩) = + EvmYul.UInt256.size - 1 - value := by + simp [EvmYul.UInt256.complement, EvmYul.UInt256.toNat, Fin.add_def, Fin.neg_def] + have hle : value + 1 ≤ EvmYul.UInt256.size := by omega + by_cases hlast : value + 1 = EvmYul.UInt256.size + · rw [hlast] + simp + omega + · have hlt : value + 1 < EvmYul.UInt256.size := Nat.lt_of_le_of_ne hle hlast + rw [Nat.mod_eq_of_lt hlt] + have hsub_lt : EvmYul.UInt256.size - (value + 1) < EvmYul.UInt256.size := by + unfold EvmYul.UInt256.size + omega + rw [Nat.mod_eq_of_lt hsub_lt] + omega + +private theorem uint256_complement_eq (value : Nat) (hv : value < EvmYul.UInt256.size) (hout) : + EvmYul.UInt256.complement ⟨⟨value, hv⟩⟩ = + ⟨⟨EvmYul.UInt256.size - 1 - value, hout⟩⟩ := by + rw [EvmYul.UInt256.mk.injEq] + apply Fin.ext + exact uint256_complement_val value hv + +private theorem uint256_shiftRight_val (value shift : Nat) + (hv : value < EvmYul.UInt256.size) (hs : shift < EvmYul.UInt256.size) : + EvmYul.UInt256.toNat (EvmYul.UInt256.shiftRight ⟨⟨value, hv⟩⟩ ⟨⟨shift, hs⟩⟩) = + if shift < 256 then value / 2 ^ shift else 0 := by + by_cases hshift : shift < 256 + · have hg : ¬ 256 ≤ (⟨⟨shift, hs⟩⟩ : EvmYul.UInt256).val := by + change ¬ 256 ≤ shift + exact Nat.not_le_of_lt hshift + simp [EvmYul.UInt256.shiftRight, EvmYul.UInt256.toNat, hg, hshift, + Nat.shiftRight_eq_div_pow] + · have hg : 256 ≤ (⟨⟨shift, hs⟩⟩ : EvmYul.UInt256).val := by + change 256 ≤ shift + exact Nat.not_lt.mp hshift + simp [EvmYul.UInt256.shiftRight, EvmYul.UInt256.toNat, hg, hshift] + +/-- EVMYulLean-side `sar` reduction through the shared Nat-level spec. -/ +private theorem uint256_sar_toNat_eq_sarSpec (shift value : Nat) + (hs : shift < EvmYul.UInt256.size) (hv : value < EvmYul.UInt256.size) : + EvmYul.UInt256.toNat (EvmYul.UInt256.sar ⟨⟨shift, hs⟩⟩ ⟨⟨value, hv⟩⟩) = + SignedArithSpec.sarSpec shift value := by + unfold EvmYul.UInt256.sar + by_cases hvalue : value < SignedArithSpec.specSignBit + · have hslFalse : EvmYul.UInt256.sltBool + (⟨⟨value, hv⟩⟩ : EvmYul.UInt256) ⟨0⟩ = false := by + unfold EvmYul.UInt256.sltBool + have hnotSign : ¬ 2 ^ 255 ≤ (⟨⟨value, hv⟩⟩ : EvmYul.UInt256).toNat := by + change ¬ 2 ^ 255 ≤ value + exact Nat.not_le_of_lt (by simpa [SignedArithSpec.specSignBit] using hvalue) + rw [if_neg hnotSign] + have hzeroNotSign : ¬ 2 ^ 255 ≤ (⟨0⟩ : EvmYul.UInt256).toNat := by decide + rw [if_neg hzeroNotSign] + simp [uint256_lt_zero_false value hv] + rw [hslFalse] + simp + show EvmYul.UInt256.toNat + (EvmYul.UInt256.shiftRight ⟨⟨value, hv⟩⟩ ⟨⟨shift, hs⟩⟩) = + SignedArithSpec.sarSpec shift value + rw [uint256_shiftRight_val value shift hv hs] + by_cases hshift : shift < 256 + · rw [SignedArithSpec.sarSpec_of_nonneg shift value hshift hvalue] + simp [hshift] + · have hge : 256 ≤ shift := Nat.not_lt.mp hshift + rw [SignedArithSpec.sarSpec_of_shift_ge_nonneg shift value hge hvalue] + simp [hshift] + · have hgeValue : SignedArithSpec.specSignBit ≤ value := Nat.le_of_not_lt hvalue + have hslTrue : EvmYul.UInt256.sltBool + (⟨⟨value, hv⟩⟩ : EvmYul.UInt256) ⟨0⟩ = true := by + unfold EvmYul.UInt256.sltBool + have hsign : 2 ^ 255 ≤ (⟨⟨value, hv⟩⟩ : EvmYul.UInt256).toNat := by + change 2 ^ 255 ≤ value + simpa [SignedArithSpec.specSignBit] using hgeValue + rw [if_pos hsign] + have hzeroNotSign : ¬ 2 ^ 255 ≤ (⟨0⟩ : EvmYul.UInt256).toNat := by decide + rw [if_neg hzeroNotSign] + rw [hslTrue] + simp + have hc_lt : EvmYul.UInt256.size - 1 - value < EvmYul.UInt256.size := by + unfold EvmYul.UInt256.size + omega + rw [uint256_complement_eq value hv hc_lt] + by_cases hshift : shift < 256 + · rw [SignedArithSpec.sarSpec_of_neg shift value hshift hgeValue] + have hdiv_lt : + (EvmYul.UInt256.size - 1 - value) / 2 ^ shift < EvmYul.UInt256.size := + Nat.lt_of_le_of_lt (Nat.div_le_self _ _) hc_lt + have hshiftEq : + EvmYul.UInt256.shiftRight + ⟨⟨EvmYul.UInt256.size - 1 - value, hc_lt⟩⟩ ⟨⟨shift, hs⟩⟩ = + ⟨⟨(EvmYul.UInt256.size - 1 - value) / 2 ^ shift, hdiv_lt⟩⟩ := by + rw [EvmYul.UInt256.mk.injEq] + apply Fin.ext + change EvmYul.UInt256.toNat + (EvmYul.UInt256.shiftRight + ⟨⟨EvmYul.UInt256.size - 1 - value, hc_lt⟩⟩ ⟨⟨shift, hs⟩⟩) = + (EvmYul.UInt256.size - 1 - value) / 2 ^ shift + rw [uint256_shiftRight_val (EvmYul.UInt256.size - 1 - value) shift hc_lt hs] + simp [hshift] + show EvmYul.UInt256.toNat + (EvmYul.UInt256.complement + (EvmYul.UInt256.shiftRight + ⟨⟨EvmYul.UInt256.size - 1 - value, hc_lt⟩⟩ ⟨⟨shift, hs⟩⟩)) = + SignedArithSpec.specModulus - 1 - + (SignedArithSpec.specModulus - 1 - value) / 2 ^ shift + rw [hshiftEq] + rw [uint256_complement_val ((EvmYul.UInt256.size - 1 - value) / 2 ^ shift) hdiv_lt] + simp [EvmYul.UInt256.size, SignedArithSpec.specModulus] + · have hge : 256 ≤ shift := Nat.not_lt.mp hshift + rw [SignedArithSpec.sarSpec_of_shift_ge_neg shift value hge hgeValue] + have hzeroLt : 0 < EvmYul.UInt256.size := by + unfold EvmYul.UInt256.size + omega + have hshiftEq : + EvmYul.UInt256.shiftRight + ⟨⟨EvmYul.UInt256.size - 1 - value, hc_lt⟩⟩ ⟨⟨shift, hs⟩⟩ = + ⟨⟨0, hzeroLt⟩⟩ := by + rw [EvmYul.UInt256.mk.injEq] + apply Fin.ext + change EvmYul.UInt256.toNat + (EvmYul.UInt256.shiftRight + ⟨⟨EvmYul.UInt256.size - 1 - value, hc_lt⟩⟩ ⟨⟨shift, hs⟩⟩) = 0 + rw [uint256_shiftRight_val (EvmYul.UInt256.size - 1 - value) shift hc_lt hs] + simp [hshift] + show EvmYul.UInt256.toNat + (EvmYul.UInt256.complement + (EvmYul.UInt256.shiftRight + ⟨⟨EvmYul.UInt256.size - 1 - value, hc_lt⟩⟩ ⟨⟨shift, hs⟩⟩)) = + SignedArithSpec.specModulus - 1 + rw [hshiftEq] + rw [uint256_complement_val 0 hzeroLt] + simp [EvmYul.UInt256.size, SignedArithSpec.specModulus] + +private theorem int_two_pow_eq_nat (shift : Nat) : + ((2 : Int) ^ shift) = Int.ofNat (2 ^ shift) := by + induction shift with + | zero => simp + | succ n ih => + rw [pow_succ, pow_succ, ih] + norm_num + +private theorem int_fdiv_ofNat_two_pow (value shift : Nat) : + (Int.ofNat value).fdiv ((2 : Int) ^ shift) = + Int.ofNat (value / 2 ^ shift) := by + rw [int_two_pow_eq_nat] + have hpos : 0 < 2 ^ shift := Nat.pow_pos (by decide : 0 < 2) + cases hp : 2 ^ shift with + | zero => omega + | succ n => + cases value with + | zero => simp [Int.fdiv] + | succ m => simp [Int.fdiv] + +private theorem int_sub_modulus_eq_negSucc (value : Nat) + (_hge : SignedArithSpec.specSignBit ≤ value) (hv : value < Compiler.Constants.evmModulus) : + Int.ofNat value - Int.ofNat Compiler.Constants.evmModulus = + Int.negSucc (Compiler.Constants.evmModulus - 1 - value) := by + unfold Compiler.Constants.evmModulus at hv ⊢ + rw [Int.negSucc_eq] + have hdiff : 2 ^ 256 - 1 - value + 1 = 2 ^ 256 - value := by omega + change Int.ofNat value - Int.ofNat (2 ^ 256) = + -Int.ofNat ((2 ^ 256 - 1 - value) + 1) + rw [hdiff] + have hcast : Int.ofNat (2 ^ 256 - value) = + Int.ofNat (2 ^ 256) - Int.ofNat value := by + exact Int.ofNat_sub (Nat.le_of_lt hv) + rw [hcast] + omega + +private theorem int_fdiv_neg_raw_two_pow (shift value : Nat) + (hge : SignedArithSpec.specSignBit ≤ value) (hv : value < Compiler.Constants.evmModulus) : + (Int.ofNat value - Int.ofNat Compiler.Constants.evmModulus).fdiv ((2 : Int) ^ shift) = + Int.negSucc ((Compiler.Constants.evmModulus - 1 - value) / 2 ^ shift) := by + rw [int_sub_modulus_eq_negSucc value hge hv] + rw [int_two_pow_eq_nat] + have hpos : 0 < 2 ^ shift := Nat.pow_pos (by decide : 0 < 2) + cases hp : 2 ^ shift with + | zero => omega + | succ n => + simp [Int.fdiv] + +private theorem int256_ofInt_negSucc_toUint256_val (n : Nat) + (hn : n + 1 < Compiler.Constants.evmModulus) : + (Verity.Core.Int256.ofInt (Int.negSucc n)).toUint256.val = + Compiler.Constants.evmModulus - (n + 1) := by + have hneg : (Int.negSucc n) < 0 := by simp + have hnatAbs : (Int.negSucc n).natAbs = n + 1 := by + have hnegSucc : Int.negSucc n = -Int.ofNat (n + 1) := by + rw [Int.negSucc_eq] + simp + rw [hnegSucc, Int.natAbs_neg] + exact Int.natAbs_natCast (n + 1) + have hmod_eq : Verity.Core.Int256.modulus = Compiler.Constants.evmModulus := by + simp [Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, + Verity.Core.UINT256_MODULUS, Compiler.Constants.evmModulus] + have hn_lt_mod : n + 1 < Verity.Core.Int256.modulus := by + rw [hmod_eq] + exact hn + have hmod_n : (n + 1) % Verity.Core.Int256.modulus = n + 1 := + Nat.mod_eq_of_lt hn_lt_mod + have hsub_lt : Verity.Core.Int256.modulus - (n + 1) < + Verity.Core.Int256.modulus := by + have hpos_mod : 0 < Verity.Core.Int256.modulus := by + rw [hmod_eq] + unfold Compiler.Constants.evmModulus + omega + omega + simp only [Verity.Core.Int256.ofInt, if_pos hneg, + Verity.Core.Int256.toUint256, Verity.Core.Int256.ofUint256, + Verity.Core.Uint256.ofNat, hnatAbs, hmod_n] + show (Verity.Core.Int256.modulus - (n + 1)) % + Verity.Core.Uint256.modulus = Compiler.Constants.evmModulus - (n + 1) + have hmod_eq' : Verity.Core.Int256.modulus = Verity.Core.Uint256.modulus := rfl + rw [hmod_eq', Nat.mod_eq_of_lt (by rw [← hmod_eq']; exact hsub_lt)] + show Verity.Core.Uint256.modulus - (n + 1) = Compiler.Constants.evmModulus - (n + 1) + rw [← hmod_eq', hmod_eq] + +private theorem int256_sar_toUint256_val_eq_sarSpec (shift value : Nat) + (hs : shift < Compiler.Constants.evmModulus) (hv : value < Compiler.Constants.evmModulus) : + (Verity.Core.Int256.sar + (Verity.Core.Int256.ofUint256 ⟨shift, hs⟩) + (Verity.Core.Int256.ofUint256 ⟨value, hv⟩)).toUint256.val = + SignedArithSpec.sarSpec shift value := by + simp [Verity.Core.Int256.sar, Verity.Core.Int256.ofUint256, + Verity.Core.Int256.toUint256] + have hsMod : shift % Verity.Core.Int256.modulus = shift := by + rw [Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, + Verity.Core.UINT256_MODULUS] + exact Nat.mod_eq_of_lt hs + rw [hsMod] + by_cases hshift : shift < 256 + · have hnot : ¬ 256 ≤ shift := Nat.not_le_of_lt hshift + rw [if_neg hnot] + by_cases hval : value < SignedArithSpec.specSignBit + · have hto : + ({ word := { val := value, isLt := hv } } : Verity.Core.Int256).toInt = + Int.ofNat value := by + rw [Verity.Core.Int256.toInt_of_lt_signBit] + simpa [Verity.Core.Int256.signBit, SignedArithSpec.specSignBit] using hval + rw [hto] + rw [SignedArithSpec.sarSpec_of_nonneg shift value hshift hval] + rw [int_fdiv_ofNat_two_pow] + have hbound : value / 2 ^ shift < Compiler.Constants.evmModulus := + Nat.lt_of_le_of_lt (Nat.div_le_self _ _) hv + exact int256_ofInt_nat_toUint256_val (value / 2 ^ shift) hbound + · have hge : SignedArithSpec.specSignBit ≤ value := Nat.le_of_not_lt hval + have hto : + ({ word := { val := value, isLt := hv } } : Verity.Core.Int256).toInt = + Int.ofNat value - Int.ofNat Compiler.Constants.evmModulus := by + rw [Verity.Core.Int256.toInt_of_ge_signBit] + · simp [Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, + Verity.Core.UINT256_MODULUS, Compiler.Constants.evmModulus] + · simpa [Verity.Core.Int256.signBit, SignedArithSpec.specSignBit] using hge + rw [hto] + rw [SignedArithSpec.sarSpec_of_neg shift value hshift hge] + rw [int_fdiv_neg_raw_two_pow shift value hge hv] + have hn_bound : (Compiler.Constants.evmModulus - 1 - value) / 2 ^ shift + 1 < Compiler.Constants.evmModulus := by + unfold Compiler.Constants.evmModulus at hv ⊢ + unfold SignedArithSpec.specSignBit at hge + have hle : (2 ^ 256 - 1 - value) / 2 ^ shift ≤ + 2 ^ 256 - 1 - value := Nat.div_le_self _ _ + omega + have hwrap := + int256_ofInt_negSucc_toUint256_val + ((Compiler.Constants.evmModulus - 1 - value) / 2 ^ shift) hn_bound + change + (Verity.Core.Int256.ofInt + (Int.negSucc ((Compiler.Constants.evmModulus - 1 - value) / 2 ^ shift))).toUint256.val = + SignedArithSpec.specModulus - 1 - + (SignedArithSpec.specModulus - 1 - value) / 2 ^ shift + rw [hwrap] + unfold SignedArithSpec.specModulus Compiler.Constants.evmModulus + omega + · have hgeShift : 256 ≤ shift := Nat.not_lt.mp hshift + rw [if_pos hgeShift] + by_cases hval : value < SignedArithSpec.specSignBit + · have hto : + ¬ ({ word := { val := value, isLt := hv } } : Verity.Core.Int256).toInt < 0 := by + rw [Verity.Core.Int256.toInt_of_lt_signBit] + · exact not_lt.mpr (Int.natCast_nonneg _) + · simpa [Verity.Core.Int256.signBit, SignedArithSpec.specSignBit] using hval + rw [if_neg hto] + rw [SignedArithSpec.sarSpec_of_shift_ge_nonneg shift value hgeShift hval] + change (Verity.Core.Uint256.ofNat 0).val = 0 + rfl + · have hge : SignedArithSpec.specSignBit ≤ value := Nat.le_of_not_lt hval + have hto : + ({ word := { val := value, isLt := hv } } : Verity.Core.Int256).toInt < 0 := by + rw [Verity.Core.Int256.toInt_of_ge_signBit] + · unfold Compiler.Constants.evmModulus at hv + unfold SignedArithSpec.specSignBit at hge + simp [Verity.Core.Int256.modulus, Verity.Core.Uint256.modulus, + Verity.Core.UINT256_MODULUS] + omega + · simpa [Verity.Core.Int256.signBit, SignedArithSpec.specSignBit] using hge + rw [if_pos hto] + rw [SignedArithSpec.sarSpec_of_shift_ge_neg shift value hgeShift hge] + have hnegOne := int256_ofInt_negSucc_toUint256_val 0 (by + unfold Compiler.Constants.evmModulus + omega) + simpa [Int.negSucc_eq, Verity.Core.Int256.toUint256, + SignedArithSpec.specModulus] using hnegOne + +/-- Core sar equivalence: Verity's `Int256.sar` agrees with EVMYulLean's `UInt256.sar`. + +Both sides reduce through `SignedArithSpec.sarSpec`: the EVMYulLean side +uses complement-shift-complement for negative words, while the Verity side +uses `Int.fdiv`; the helpers above identify the negative `fdiv` branch with +the same two's-complement raw-word result. -/ +theorem int256_sar_toUint256_val_eq_uint256_sar (shift value : Nat) + (hs : shift < Compiler.Constants.evmModulus) (hv : value < Compiler.Constants.evmModulus) : + (Verity.Core.Int256.sar + (Verity.Core.Int256.ofUint256 ⟨shift, hs⟩) + (Verity.Core.Int256.ofUint256 ⟨value, hv⟩)).toUint256.val = + EvmYul.UInt256.toNat (EvmYul.UInt256.sar ⟨⟨shift, by rw [EvmYul.UInt256.size]; exact hs⟩⟩ + ⟨⟨value, by rw [EvmYul.UInt256.size]; exact hv⟩⟩) := by + rw [uint256_sar_toNat_eq_sarSpec] + exact int256_sar_toUint256_val_eq_sarSpec shift value hs hv +private theorem se_uint256_eq_of_val (a b : EvmYul.UInt256) (h : a.val.val = b.val.val) : + a = b := by cases a; cases b; congr 1; ext; exact h + +private theorem se_lor_val (a b : EvmYul.UInt256) : + (EvmYul.UInt256.lor a b).val.val = (a.val.val ||| b.val.val) % EvmYul.UInt256.size := by + unfold EvmYul.UInt256.lor; simp only [Fin.lor]; rfl + +private theorem se_land_val (a b : EvmYul.UInt256) : + (EvmYul.UInt256.land a b).val.val = (a.val.val &&& b.val.val) % EvmYul.UInt256.size := by + unfold EvmYul.UInt256.land; simp only [Fin.land]; rfl + +private theorem se_sub_val (a b : EvmYul.UInt256) : + (EvmYul.UInt256.sub a b).val.val = + (EvmYul.UInt256.size - b.val.val + a.val.val) % EvmYul.UInt256.size := by + unfold EvmYul.UInt256.sub; simp only [Fin.sub_def] + +private theorem se_tb_pow_sub_pow {n k : Nat} (hkn : k ≤ n) (i : Nat) : + (2^n - 2^k).testBit i = (decide (k ≤ i) && decide (i < n)) := by + have := Nat.one_le_pow k 2 (by omega) + have := Nat.pow_le_pow_right (show 0 < 2 from by omega) hkn + rw [show 2^k = (2^k - 1) + 1 from by omega, + Nat.testBit_two_pow_sub_succ (by omega), + Nat.testBit_two_pow_sub_one] + by_cases h1 : i < k <;> by_cases h2 : i < n <;> simp_all + +private theorem se_tb_ne_zero {v k : Nat} (h : v &&& 2^k ≠ 0) : v.testBit k = true := by + by_contra hf; simp only [Bool.not_eq_true] at hf + apply h; apply Nat.eq_of_testBit_eq; intro i + simp only [Nat.testBit_and, Nat.testBit_two_pow, Nat.zero_testBit] + by_cases hik : k = i + · subst hik; simp [hf] + · simp [hik] + +private theorem se_tb_eq_zero {v k : Nat} (h : v &&& 2^k = 0) : v.testBit k = false := by + by_contra hf; simp only [Bool.not_eq_false] at hf + have : (v &&& 2^k).testBit k = true := by simp [Nat.testBit_and, hf] + rw [h] at this; simp at this + +private theorem se_set_eq {v n k : Nat} (hk1n : k + 1 ≤ n) (hsign : v &&& 2^k ≠ 0) : + v ||| (2^n - 2^(k+1)) = v ||| (2^n - 2^k) := by + have hbit := se_tb_ne_zero hsign + apply Nat.eq_of_testBit_eq; intro i + simp only [Nat.testBit_or, se_tb_pow_sub_pow (by omega : k + 1 ≤ n), + se_tb_pow_sub_pow (by omega : k ≤ n)] + by_cases hik : i = k + · subst hik; simp [hbit] + · congr 1 + by_cases hi : i < k + · simp [show ¬(k ≤ i) from by omega, show ¬(k+1 ≤ i) from by omega] + · simp [show k ≤ i from by omega, show k+1 ≤ i from by omega] + +private theorem se_clear_eq {v k : Nat} (hsign : v &&& 2^k = 0) : + v &&& (2^(k+1) - 1) = v &&& (2^k - 1) := by + have hbit := se_tb_eq_zero hsign + apply Nat.eq_of_testBit_eq; intro i + simp only [Nat.testBit_and, Nat.testBit_two_pow_sub_one] + by_cases hik : i = k + · subst hik; simp [hbit, show i < i + 1 from by omega] + · congr 1; congr 1 + by_cases hi : i < k + · simp [hi, show i < k + 1 from by omega] + · simp [show ¬(i < k) from hi, show ¬(i < k + 1) from by omega] + +set_option maxHeartbeats 4000000 in +private theorem se_tb_val (byteIdx : Nat) (hb : byteIdx < EvmYul.UInt256.size) + (hle : byteIdx ≤ 31) : + (({ val := ⟨byteIdx, hb⟩ } : EvmYul.UInt256) * { val := 8 } + { val := 7 }).val.val = + byteIdx * 8 + 7 := by + show ((EvmYul.UInt256.add (EvmYul.UInt256.mul ⟨⟨byteIdx, hb⟩⟩ ⟨8⟩) ⟨7⟩)).val.val = _ + unfold EvmYul.UInt256.add EvmYul.UInt256.mul + simp only [Fin.mul_def, Fin.add_def] + have h8 : (8 : Fin EvmYul.UInt256.size).val = 8 := by simp [EvmYul.UInt256.size] + have h7 : (7 : Fin EvmYul.UInt256.size).val = 7 := by simp [EvmYul.UInt256.size] + rw [h8, h7, Nat.mod_eq_of_lt (by rw [EvmYul.UInt256.size]; omega), + Nat.mod_eq_of_lt (by rw [EvmYul.UInt256.size]; omega)] + +private theorem se_shiftLeft_one_val (bitPos : Nat) (hbp : bitPos ≤ 255) : + (EvmYul.UInt256.shiftLeft ⟨⟨1, by rw [EvmYul.UInt256.size]; omega⟩⟩ + ⟨⟨bitPos, by rw [EvmYul.UInt256.size]; omega⟩⟩).val.val = 2^bitPos := by + unfold EvmYul.UInt256.shiftLeft; split + · rename_i h; exact absurd (show bitPos ≥ 256 from h) (by omega) + · change (1 <<< bitPos) % EvmYul.UInt256.size = 2^bitPos + simp only [Nat.shiftLeft_eq, Nat.one_mul] + have : 2^bitPos < 2^256 := Nat.pow_lt_pow_right (by omega) (by omega) + rw [EvmYul.UInt256.size]; exact Nat.mod_eq_of_lt this + +private theorem se_val_val_of_eq (a b : EvmYul.UInt256) (h : a = b) : + a.val.val = b.val.val := by subst h; rfl + +private theorem se_sign_set (value : Nat) (hvS : value < EvmYul.UInt256.size) + (sb : EvmYul.UInt256) (bp : Nat) (hsb : sb.val.val = 2^bp) + (h : EvmYul.UInt256.land ⟨⟨value, hvS⟩⟩ sb ≠ + ⟨⟨0, by rw [EvmYul.UInt256.size]; omega⟩⟩) : + value &&& 2^bp ≠ 0 := by + intro heq; apply h; apply se_uint256_eq_of_val + rw [se_land_val, hsb, heq]; simp [EvmYul.UInt256.size] + +private theorem se_sign_clear (value : Nat) (hvS : value < EvmYul.UInt256.size) + (sb : EvmYul.UInt256) (bp : Nat) (hsb : sb.val.val = 2^bp) + (h : ¬(EvmYul.UInt256.land ⟨⟨value, hvS⟩⟩ sb ≠ + ⟨⟨0, by rw [EvmYul.UInt256.size]; omega⟩⟩)) : + value &&& 2^bp = 0 := by + push_neg at h + have h1 := se_val_val_of_eq _ _ h + rw [se_land_val, hsb] at h1 + rwa [Nat.mod_eq_of_lt (Nat.lt_of_le_of_lt Nat.and_le_left hvS)] at h1 + +private theorem se_nat_to_sign (value : Nat) (hvS : value < EvmYul.UInt256.size) + (sb : EvmYul.UInt256) (bp : Nat) (hsb : sb.val.val = 2^bp) + (h : value &&& 2^bp ≠ 0) : + EvmYul.UInt256.land ⟨⟨value, hvS⟩⟩ sb ≠ + ⟨⟨0, by rw [EvmYul.UInt256.size]; omega⟩⟩ := by + intro heq; apply h + have h1 := se_val_val_of_eq _ _ heq + rw [se_land_val, hsb] at h1 + rwa [Nat.mod_eq_of_lt (Nat.lt_of_le_of_lt Nat.and_le_left hvS)] at h1 + +private theorem se_verity_ofNat (n : Nat) : + (Verity.Core.Uint256.ofNat n).val = n % Compiler.Constants.evmModulus := by + unfold Verity.Core.Uint256.ofNat Verity.Core.Uint256.modulus + Verity.Core.UINT256_MODULUS Compiler.Constants.evmModulus + simp + +private theorem se_size_to_uint256_val : + (EvmYul.UInt256.size.toUInt256 : EvmYul.UInt256).val.val = 0 := by + simp [Nat.toUInt256, EvmYul.UInt256.ofNat, Id.run, EvmYul.UInt256.size] + +set_option maxHeartbeats 16000000 in +/-- Core signextend equivalence: Verity's `Uint256.signextend` agrees with +EVMYulLean's `UInt256.signextend`. + +Both implement EVM SIGNEXTEND using the same bit-level algorithm: +1. Compute sign bit position = byteIdx * 8 + 7 +2. Test the sign bit +3. If set: fill high bits (OR with complement mask) +4. If clear: clear high bits (AND with mask) +5. If byteIdx ≥ 31: return value unchanged -/ +theorem uint256_signextend_val_eq_uint256_signextend (byteIdx value : Nat) + (hb : byteIdx < Compiler.Constants.evmModulus) (hv : value < Compiler.Constants.evmModulus) : + (Verity.Core.Uint256.signextend ⟨byteIdx, hb⟩ ⟨value, hv⟩).val = + EvmYul.UInt256.toNat (EvmYul.UInt256.signextend + ⟨⟨byteIdx, by rw [EvmYul.UInt256.size]; exact hb⟩⟩ + ⟨⟨value, by rw [EvmYul.UInt256.size]; exact hv⟩⟩) := by + have hvS : value < EvmYul.UInt256.size := by rw [EvmYul.UInt256.size]; exact hv + have hbS : byteIdx < EvmYul.UInt256.size := by rw [EvmYul.UInt256.size]; exact hb + have hv256 : value < 2^256 := by rw [show (2:Nat)^256 = Compiler.Constants.evmModulus from rfl]; exact hv + unfold Verity.Core.Uint256.signextend EvmYul.UInt256.signextend + simp only [EvmYul.UInt256.toNat] + by_cases hle31 : byteIdx ≤ 31 + · -- byteIdx ≤ 31: EVMYulLean does signextend + simp only [hle31, ite_true] + set bitPos := byteIdx * 8 + 7 + have hbp : bitPos ≤ 255 := by omega + have hbpS : bitPos < EvmYul.UInt256.size := by rw [EvmYul.UInt256.size]; omega + have hpow_pos := Nat.one_le_pow bitPos 2 (by omega) + have hpow_lt := Nat.pow_lt_pow_right (show 1 < 2 from by omega) + (show bitPos < 256 from by omega) + have htb_val := se_tb_val byteIdx hbS hle31 + set tb := ({ val := ⟨byteIdx, hbS⟩ } : EvmYul.UInt256) * { val := 8 } + { val := 7 } + have htbvv : tb.val.val = bitPos := htb_val + have htb_eq : tb = ⟨⟨bitPos, hbpS⟩⟩ := se_uint256_eq_of_val _ _ htbvv + set sb := EvmYul.UInt256.shiftLeft ⟨⟨1, by rw [EvmYul.UInt256.size]; omega⟩⟩ tb + have hsb_val : sb.val.val = 2^bitPos := by + show (EvmYul.UInt256.shiftLeft ⟨⟨1, _⟩⟩ tb).val.val = 2^bitPos + rw [htb_eq]; exact se_shiftLeft_one_val bitPos hbp + have hmod_sub : (2^256 - 2^bitPos) % 2^256 = 2^256 - 2^bitPos := + Nat.mod_eq_of_lt (by omega) + have hmod_mask : (2^bitPos - 1) % 2^256 = 2^bitPos - 1 := + Nat.mod_eq_of_lt (by omega) + by_cases hge31 : byteIdx ≥ 31 + · -- byteIdx = 31: Verity identity, EVMYulLean signextend at bitPos=255 + have hb31 : byteIdx = 31 := by omega + simp only [hb31, show (31 : Nat) ≥ 31 from le_refl _, ite_true] + have hbp255 : bitPos = 255 := by omega + split + · -- sign set + rename_i hsign + change value = (EvmYul.UInt256.lor ⟨⟨value, hvS⟩⟩ + (EvmYul.UInt256.sub EvmYul.UInt256.size.toUInt256 sb)).val.val + rw [se_lor_val, se_sub_val, se_size_to_uint256_val, hsb_val] + simp only [show EvmYul.UInt256.size = 2^256 from rfl] + simp only [Nat.add_zero, hmod_sub] + have hsign_nat := se_sign_set value hvS sb bitPos hsb_val hsign + rw [hbp255] at hsign_nat ⊢ + rw [show (2:Nat)^256 - 2^255 = 2^255 from by omega] + have hbit := se_tb_ne_zero hsign_nat + have hor : value ||| 2^255 = value := by + apply Nat.eq_of_testBit_eq; intro i + simp only [Nat.testBit_or, Nat.testBit_two_pow] + by_cases hik : 255 = i + · subst hik; simp [hbit] + · simp [hik] + rw [hor, Nat.mod_eq_of_lt hv256] + · -- sign clear + rename_i hsign + change value = (EvmYul.UInt256.land ⟨⟨value, hvS⟩⟩ + (EvmYul.UInt256.sub sb ⟨⟨1, by rw [EvmYul.UInt256.size]; omega⟩⟩)).val.val + rw [se_land_val, se_sub_val, hsb_val] + simp only [show EvmYul.UInt256.size = 2^256 from rfl] + rw [show (2:Nat)^256 - 1 + 2^bitPos = (2^bitPos - 1) + 1 * 2^256 from by omega, + Nat.add_mul_mod_self_right, hmod_mask] + have hsign_nat := se_sign_clear value hvS sb bitPos hsb_val hsign + rw [hbp255] at hsign_nat ⊢ + have htb_false := se_tb_eq_zero hsign_nat + have hv255 : value < 2^255 := by + apply Nat.lt_of_testBit 255 htb_false + · rw [Nat.testBit_two_pow]; simp + · intro j hj + have hj256 : 256 ≤ j := by omega + have hvj : value < 2^j := + lt_of_lt_of_le hv256 (Nat.pow_le_pow_right (by omega) hj256) + rw [Nat.testBit_lt_two_pow hvj, Nat.testBit_two_pow_of_ne (by omega)] + have hmask : value &&& (2^255 - 1) = value := by + apply Nat.eq_of_testBit_eq; intro i + simp only [Nat.testBit_and, Nat.testBit_two_pow_sub_one] + by_cases hi : i < 255 + · simp [hi] + · have hi255 : 255 ≤ i := by omega + have hvi : value < 2^i := + lt_of_lt_of_le hv255 (Nat.pow_le_pow_right (by omega) hi255) + simp [show ¬(i < 255) from hi, Nat.testBit_lt_two_pow hvi] + rw [hmask, Nat.mod_eq_of_lt hv256] + · -- byteIdx ≤ 30: both do signextend + simp only [show ¬(byteIdx ≥ 31) from hge31, ite_false] + have hle30 : byteIdx ≤ 30 := by omega + have hbp254 : bitPos ≤ 254 := by omega + split + · -- Verity set + rename_i hsign_nat + rw [se_verity_ofNat] + unfold Verity.Core.Uint256.modulus Verity.Core.UINT256_MODULUS + rw [show 2^256 - 1 - (2 ^ (bitPos + 1) - 1) = 2^256 - 2^(bitPos+1) from by + have := Nat.one_le_pow (bitPos + 1) 2 (by omega) + have := Nat.pow_lt_pow_right (show 1 < 2 from by omega) + (show bitPos + 1 < 256 from by omega) + omega] + split + · -- EVMYulLean set → prove equality + rename_i hsign_evm + change _ = (EvmYul.UInt256.lor ⟨⟨value, hvS⟩⟩ + (EvmYul.UInt256.sub EvmYul.UInt256.size.toUInt256 sb)).val.val + rw [se_lor_val, se_sub_val, se_size_to_uint256_val, hsb_val] + simp only [show EvmYul.UInt256.size = 2^256 from rfl] + simp only [Nat.add_zero, hmod_sub] + unfold Compiler.Constants.evmModulus + rw [se_set_eq (by omega) hsign_nat] + · -- EVMYulLean clear → contradiction + rename_i hsign_evm + exfalso; exact hsign_evm (se_nat_to_sign value hvS sb bitPos hsb_val hsign_nat) + · -- Verity clear + rename_i hsign + have hsign_nat : value &&& 2^bitPos = 0 := not_not.mp hsign + rw [se_verity_ofNat] + split + · -- EVMYulLean set → contradiction + rename_i hsign_evm + exfalso + have := se_sign_set value hvS sb bitPos hsb_val hsign_evm + exact hsign this + · -- EVMYulLean clear → prove equality + rename_i hsign_evm + change _ = (EvmYul.UInt256.land ⟨⟨value, hvS⟩⟩ + (EvmYul.UInt256.sub sb ⟨⟨1, by rw [EvmYul.UInt256.size]; omega⟩⟩)).val.val + rw [se_land_val, se_sub_val, hsb_val] + simp only [show EvmYul.UInt256.size = 2^256 from rfl] + rw [show (2:Nat)^256 - 1 + 2^bitPos = (2^bitPos - 1) + 1 * 2^256 from by omega, + Nat.add_mul_mod_self_right, hmod_mask] + unfold Compiler.Constants.evmModulus + rw [se_clear_eq hsign_nat] + · -- byteIdx > 31: identity for both + simp only [show ¬(byteIdx ≤ 31) from hle31, ite_false] + simp only [show byteIdx ≥ 31 from by omega, ite_true] +end Compiler.Proofs.YulGeneration.Backends diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeSmokeTest.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeSmokeTest.lean index be0329320..8a84eb7a7 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeSmokeTest.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeSmokeTest.lean @@ -1,4 +1,5 @@ import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanNativeHarness +import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics import EvmYul.Yul.Interpreter namespace Compiler.Proofs.YulGeneration.Backends @@ -155,7 +156,7 @@ private def referenceRuntimeWithFuel (storage : IRStorageSlot → IRStorageWord) (events : List (List Nat)) : Compiler.Proofs.YulGeneration.YulResult := let initialState := Compiler.Proofs.YulGeneration.YulState.initial tx storage events - match Compiler.Proofs.YulGeneration.execYulFuel fuel initialState (.stmts stmts) with + match Compiler.Proofs.YulGeneration.legacyExecYulFuel fuel initialState (.stmts stmts) with | .continue s => { success := true returnValue := s.returnValue @@ -1082,6 +1083,10 @@ example : nativeRejectsUnsupportedHeaderBuiltin "gaslimit" = true := by native_decide +example : + nativeRejectsUnsupportedHeaderBuiltin "selfbalance" = true := by + native_decide + example : nativeStoresBuiltin "caller" 12 sampleTx.sender = true := by native_decide diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanPureBuiltinLemmas.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanPureBuiltinLemmas.lean new file mode 100644 index 000000000..1e632388c --- /dev/null +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanPureBuiltinLemmas.lean @@ -0,0 +1,536 @@ +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanAdapter +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanNativeSignedArithLemmas +import Mathlib.Data.Nat.Bitwise +import Verity.Core.Int256 +import Verity.Core.Uint256 + +namespace Compiler.Proofs.YulGeneration.Backends + +private theorem uint256_size_eq_evmModulus : + EvmYul.UInt256.size = Compiler.Constants.evmModulus := by + decide + +private theorem word_lt_uint256_size (x : Nat) : + x % EvmYul.UInt256.size < 2 ^ 256 := by + simpa [EvmYul.UInt256.size] using Nat.mod_lt x (by decide : 0 < EvmYul.UInt256.size) + +@[simp] theorem evalPureBuiltinViaEvmYulLean_add_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "add" [a, b] = + some ((a + b) % Compiler.Constants.evmModulus) := by + rw [← uint256_size_eq_evmModulus] + change some ((Fin.ofNat EvmYul.UInt256.size a + Fin.ofNat EvmYul.UInt256.size b).val) = + some ((a + b) % EvmYul.UInt256.size) + simp [Fin.val_add, Nat.add_mod] + +@[simp] theorem evalPureBuiltinViaEvmYulLean_sub_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "sub" [a, b] = + some ((Compiler.Constants.evmModulus + (a % Compiler.Constants.evmModulus) - + (b % Compiler.Constants.evmModulus)) % Compiler.Constants.evmModulus) := by + rw [← uint256_size_eq_evmModulus] + change some ((Fin.ofNat EvmYul.UInt256.size a - Fin.ofNat EvmYul.UInt256.size b).val) = + some ((EvmYul.UInt256.size + a % EvmYul.UInt256.size - b % EvmYul.UInt256.size) % + EvmYul.UInt256.size) + have hsub : + EvmYul.UInt256.size + a % EvmYul.UInt256.size - b % EvmYul.UInt256.size = + EvmYul.UInt256.size - b % EvmYul.UInt256.size + a % EvmYul.UInt256.size := by + have hb : b % EvmYul.UInt256.size ≤ EvmYul.UInt256.size := by + exact Nat.le_of_lt (Nat.mod_lt _ (by simp [EvmYul.UInt256.size])) + omega + simp [Fin.sub_def, Nat.add_mod, hsub] + +@[simp] theorem evalPureBuiltinViaEvmYulLean_mul_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "mul" [a, b] = + some ((a * b) % Compiler.Constants.evmModulus) := by + rw [← uint256_size_eq_evmModulus] + change some ((Fin.ofNat EvmYul.UInt256.size a * Fin.ofNat EvmYul.UInt256.size b).val) = + some ((a * b) % EvmYul.UInt256.size) + simp [Fin.mul_def, Nat.mul_mod] + +@[simp] theorem evalPureBuiltinViaEvmYulLean_div_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "div" [a, b] = + some (if b % Compiler.Constants.evmModulus = 0 then 0 else + (a % Compiler.Constants.evmModulus) / (b % Compiler.Constants.evmModulus)) := by + rw [← uint256_size_eq_evmModulus] + change some ((Fin.ofNat EvmYul.UInt256.size a / Fin.ofNat EvmYul.UInt256.size b).val) = + some (if b % EvmYul.UInt256.size = 0 then 0 else + (a % EvmYul.UInt256.size) / (b % EvmYul.UInt256.size)) + by_cases hb : b % EvmYul.UInt256.size = 0 <;> simp [hb] + +@[simp] theorem evalPureBuiltinViaEvmYulLean_mod_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "mod" [a, b] = + some (if b % Compiler.Constants.evmModulus = 0 then 0 else + (a % Compiler.Constants.evmModulus) % (b % Compiler.Constants.evmModulus)) := by + rw [← uint256_size_eq_evmModulus] + change some (EvmYul.UInt256.toNat + (EvmYul.UInt256.mod (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b))) = + some (if b % EvmYul.UInt256.size = 0 then 0 else + (a % EvmYul.UInt256.size) % (b % EvmYul.UInt256.size)) + by_cases hb : b % EvmYul.UInt256.size = 0 + · have hb0val : ((EvmYul.UInt256.ofNat b).val).val = 0 := by + change b % EvmYul.UInt256.size = 0 + exact hb + have hb0 : (EvmYul.UInt256.ofNat b).val = 0 := Fin.ext hb0val + simp [EvmYul.UInt256.mod, EvmYul.UInt256.toNat, hb, hb0] + · have hb0 : ¬ (EvmYul.UInt256.ofNat b).val = 0 := by + intro h + exact hb (congrArg Fin.val h) + rw [show EvmYul.UInt256.mod (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b) = + ⟨(EvmYul.UInt256.ofNat a).val % (EvmYul.UInt256.ofNat b).val⟩ by + simp [EvmYul.UInt256.mod, hb0]] + simp [hb, EvmYul.UInt256.toNat] + rfl + +@[simp] theorem evalPureBuiltinViaEvmYulLean_eq_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "eq" [a, b] = + some (if a % Compiler.Constants.evmModulus = b % Compiler.Constants.evmModulus then 1 else 0) := by + rw [← uint256_size_eq_evmModulus] + rfl + +@[simp] theorem evalPureBuiltinViaEvmYulLean_iszero_native (a : Nat) : + evalPureBuiltinViaEvmYulLean "iszero" [a] = + some (if a % Compiler.Constants.evmModulus = 0 then 1 else 0) := by + rw [← uint256_size_eq_evmModulus] + rfl + +@[simp] theorem evalPureBuiltinViaEvmYulLean_lt_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "lt" [a, b] = + some (if a % Compiler.Constants.evmModulus < b % Compiler.Constants.evmModulus then 1 else 0) := by + rw [← uint256_size_eq_evmModulus] + rfl + +@[simp] theorem evalPureBuiltinViaEvmYulLean_gt_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "gt" [a, b] = + some (if b % Compiler.Constants.evmModulus < a % Compiler.Constants.evmModulus then 1 else 0) := by + rw [← uint256_size_eq_evmModulus] + rfl + +private theorem toNat_fromBool (b : Bool) : + EvmYul.UInt256.toNat (Bool.toUInt256 b) = if b then 1 else 0 := by + cases b <;> rfl + +private theorem uint256_lt_iff_nat_lt {a b : Nat} + (ha : a < EvmYul.UInt256.size) (hb : b < EvmYul.UInt256.size) : + ((⟨⟨a, ha⟩⟩ : EvmYul.UInt256) < ⟨⟨b, hb⟩⟩) ↔ (a < b) := + Iff.rfl + +private theorem slt_int256_eq_sltBool (a b : Nat) + (ha : a < Compiler.Constants.evmModulus) + (hb : b < Compiler.Constants.evmModulus) : + (if Verity.Core.Int256.toInt (Verity.Core.Int256.ofUint256 ⟨a, ha⟩) < + Verity.Core.Int256.toInt (Verity.Core.Int256.ofUint256 ⟨b, hb⟩) + then (1 : Nat) else 0) = + (EvmYul.UInt256.toNat + (EvmYul.UInt256.slt ⟨⟨a, by simpa [uint256_size_eq_evmModulus] using ha⟩⟩ + ⟨⟨b, by simpa [uint256_size_eq_evmModulus] using hb⟩⟩)) := by + unfold EvmYul.UInt256.slt + rw [toNat_fromBool] + unfold EvmYul.UInt256.sltBool + simp only [EvmYul.UInt256.toNat, ge_iff_le] + have ha' : a < EvmYul.UInt256.size := by simpa [uint256_size_eq_evmModulus] using ha + have hb' : b < EvmYul.UInt256.size := by simpa [uint256_size_eq_evmModulus] using hb + simp only [uint256_lt_iff_nat_lt ha' hb'] + simp only [Verity.Core.Int256.toInt, Verity.Core.Int256.ofUint256, + Verity.Core.Int256.signBit, Verity.Core.Int256.modulus, + Verity.Core.Uint256.modulus, Verity.Core.UINT256_MODULUS] + split_ifs <;> simp_all [Compiler.Constants.evmModulus, EvmYul.UInt256.size] <;> omega + +@[simp] theorem evalPureBuiltinViaEvmYulLean_slt_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "slt" [a, b] = + some (if Verity.Core.Int256.toInt + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) < + Verity.Core.Int256.toInt + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus))) + then 1 else 0) := by + have ha : a % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt a (by unfold Compiler.Constants.evmModulus; omega) + have hb : b % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt b (by unfold Compiler.Constants.evmModulus; omega) + change some (EvmYul.UInt256.toNat + (EvmYul.UInt256.slt (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b))) = + some (if Verity.Core.Int256.toInt + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) < + Verity.Core.Int256.toInt + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus))) + then 1 else 0) + congr 1 + rw [show EvmYul.UInt256.ofNat a = + (⟨⟨a % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using ha⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + rw [show EvmYul.UInt256.ofNat b = + (⟨⟨b % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using hb⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + have hmod_a : + (a % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + a % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using ha) + have hmod_b : + (b % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + b % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using hb) + simp only [Verity.Core.Uint256.ofNat, Verity.Core.Uint256.modulus, hmod_a, hmod_b] + exact (slt_int256_eq_sltBool + (a % Compiler.Constants.evmModulus) (b % Compiler.Constants.evmModulus) ha hb).symm + +private theorem sgt_int256_eq_sgtBool (a b : Nat) + (ha : a < Compiler.Constants.evmModulus) + (hb : b < Compiler.Constants.evmModulus) : + (if Verity.Core.Int256.toInt (Verity.Core.Int256.ofUint256 ⟨b, hb⟩) < + Verity.Core.Int256.toInt (Verity.Core.Int256.ofUint256 ⟨a, ha⟩) + then (1 : Nat) else 0) = + (EvmYul.UInt256.toNat + (EvmYul.UInt256.sgt ⟨⟨a, by simpa [uint256_size_eq_evmModulus] using ha⟩⟩ + ⟨⟨b, by simpa [uint256_size_eq_evmModulus] using hb⟩⟩)) := by + unfold EvmYul.UInt256.sgt + rw [toNat_fromBool] + unfold EvmYul.UInt256.sgtBool + simp only [EvmYul.UInt256.toNat, ge_iff_le] + have ha' : a < EvmYul.UInt256.size := by simpa [uint256_size_eq_evmModulus] using ha + have hb' : b < EvmYul.UInt256.size := by simpa [uint256_size_eq_evmModulus] using hb + simp only [uint256_lt_iff_nat_lt hb' ha'] + simp only [Verity.Core.Int256.toInt, Verity.Core.Int256.ofUint256, + Verity.Core.Int256.signBit, Verity.Core.Int256.modulus, + Verity.Core.Uint256.modulus, Verity.Core.UINT256_MODULUS] + split_ifs <;> simp_all [Compiler.Constants.evmModulus, EvmYul.UInt256.size] <;> omega + +@[simp] theorem evalPureBuiltinViaEvmYulLean_sgt_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "sgt" [a, b] = + some (if Verity.Core.Int256.toInt + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus))) < + Verity.Core.Int256.toInt + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) + then 1 else 0) := by + have ha : a % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt a (by unfold Compiler.Constants.evmModulus; omega) + have hb : b % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt b (by unfold Compiler.Constants.evmModulus; omega) + change some (EvmYul.UInt256.toNat + (EvmYul.UInt256.sgt (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b))) = + some (if Verity.Core.Int256.toInt + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus))) < + Verity.Core.Int256.toInt + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) + then 1 else 0) + congr 1 + rw [show EvmYul.UInt256.ofNat a = + (⟨⟨a % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using ha⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + rw [show EvmYul.UInt256.ofNat b = + (⟨⟨b % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using hb⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + have hmod_a : + (a % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + a % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using ha) + have hmod_b : + (b % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + b % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using hb) + simp only [Verity.Core.Uint256.ofNat, Verity.Core.Uint256.modulus, hmod_a, hmod_b] + exact (sgt_int256_eq_sgtBool + (a % Compiler.Constants.evmModulus) (b % Compiler.Constants.evmModulus) ha hb).symm + +@[simp] theorem evalPureBuiltinViaEvmYulLean_sdiv_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "sdiv" [a, b] = + some (Verity.Core.Int256.div + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus)))).toUint256.val := by + have ha : a % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt a (by unfold Compiler.Constants.evmModulus; omega) + have hb : b % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt b (by unfold Compiler.Constants.evmModulus; omega) + change some (EvmYul.UInt256.toNat + (EvmYul.UInt256.sdiv (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b))) = + some (Verity.Core.Int256.div + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus)))).toUint256.val + congr 1 + rw [show EvmYul.UInt256.ofNat a = + (⟨⟨a % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using ha⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + rw [show EvmYul.UInt256.ofNat b = + (⟨⟨b % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using hb⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + have hmod_a : + (a % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + a % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using ha) + have hmod_b : + (b % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + b % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using hb) + simp only [Verity.Core.Uint256.ofNat, Verity.Core.Uint256.modulus, hmod_a, hmod_b] + exact (int256_div_toUint256_val_eq_uint256_sdiv + (a % Compiler.Constants.evmModulus) (b % Compiler.Constants.evmModulus) ha hb).symm + +@[simp] theorem evalPureBuiltinViaEvmYulLean_smod_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "smod" [a, b] = + some (Verity.Core.Int256.mod + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus)))).toUint256.val := by + have ha : a % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt a (by unfold Compiler.Constants.evmModulus; omega) + have hb : b % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt b (by unfold Compiler.Constants.evmModulus; omega) + change some (EvmYul.UInt256.toNat + (EvmYul.UInt256.smod (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b))) = + some (Verity.Core.Int256.mod + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (a % Compiler.Constants.evmModulus))) + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (b % Compiler.Constants.evmModulus)))).toUint256.val + congr 1 + rw [show EvmYul.UInt256.ofNat a = + (⟨⟨a % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using ha⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + rw [show EvmYul.UInt256.ofNat b = + (⟨⟨b % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using hb⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + have hmod_a : + (a % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + a % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using ha) + have hmod_b : + (b % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + b % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using hb) + simp only [Verity.Core.Uint256.ofNat, Verity.Core.Uint256.modulus, hmod_a, hmod_b] + exact (int256_mod_toUint256_val_eq_uint256_smod + (a % Compiler.Constants.evmModulus) (b % Compiler.Constants.evmModulus) ha hb).symm + +@[simp] theorem evalPureBuiltinViaEvmYulLean_sar_native (shift value : Nat) : + evalPureBuiltinViaEvmYulLean "sar" [shift, value] = + some (Verity.Core.Int256.sar + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (shift % Compiler.Constants.evmModulus))) + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (value % Compiler.Constants.evmModulus)))).toUint256.val := by + have hs : shift % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt shift (by unfold Compiler.Constants.evmModulus; omega) + have hv : value % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt value (by unfold Compiler.Constants.evmModulus; omega) + change some (EvmYul.UInt256.toNat + (EvmYul.UInt256.sar (EvmYul.UInt256.ofNat shift) (EvmYul.UInt256.ofNat value))) = + some (Verity.Core.Int256.sar + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (shift % Compiler.Constants.evmModulus))) + (Verity.Core.Int256.ofUint256 + (Verity.Core.Uint256.ofNat (value % Compiler.Constants.evmModulus)))).toUint256.val + congr 1 + rw [show EvmYul.UInt256.ofNat shift = + (⟨⟨shift % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using hs⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + rw [show EvmYul.UInt256.ofNat value = + (⟨⟨value % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using hv⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + have hmod_s : + (shift % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + shift % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using hs) + have hmod_v : + (value % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + value % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using hv) + simp only [Verity.Core.Uint256.ofNat, Verity.Core.Uint256.modulus, hmod_s, hmod_v] + exact (int256_sar_toUint256_val_eq_uint256_sar + (shift % Compiler.Constants.evmModulus) (value % Compiler.Constants.evmModulus) hs hv).symm + +@[simp] theorem evalPureBuiltinViaEvmYulLean_signextend_native (byteIdx value : Nat) : + evalPureBuiltinViaEvmYulLean "signextend" [byteIdx, value] = + some (Verity.Core.Uint256.signextend + (Verity.Core.Uint256.ofNat (byteIdx % Compiler.Constants.evmModulus)) + (Verity.Core.Uint256.ofNat (value % Compiler.Constants.evmModulus))).val := by + have hb : byteIdx % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt byteIdx (by unfold Compiler.Constants.evmModulus; omega) + have hv : value % Compiler.Constants.evmModulus < Compiler.Constants.evmModulus := + Nat.mod_lt value (by unfold Compiler.Constants.evmModulus; omega) + change some (EvmYul.UInt256.toNat + (EvmYul.UInt256.signextend (EvmYul.UInt256.ofNat byteIdx) (EvmYul.UInt256.ofNat value))) = + some (Verity.Core.Uint256.signextend + (Verity.Core.Uint256.ofNat (byteIdx % Compiler.Constants.evmModulus)) + (Verity.Core.Uint256.ofNat (value % Compiler.Constants.evmModulus))).val + congr 1 + rw [show EvmYul.UInt256.ofNat byteIdx = + (⟨⟨byteIdx % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using hb⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + rw [show EvmYul.UInt256.ofNat value = + (⟨⟨value % Compiler.Constants.evmModulus, by + simpa [uint256_size_eq_evmModulus] using hv⟩⟩ : EvmYul.UInt256) by + simp only [EvmYul.UInt256.ofNat, Id.run]; congr 1] + have hmod_b : + (byteIdx % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + byteIdx % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using hb) + have hmod_v : + (value % Compiler.Constants.evmModulus) % Verity.Core.UINT256_MODULUS = + value % Compiler.Constants.evmModulus := by + exact Nat.mod_eq_of_lt (by simpa [Compiler.Constants.evmModulus, Verity.Core.UINT256_MODULUS] using hv) + simp only [Verity.Core.Uint256.ofNat, Verity.Core.Uint256.modulus, hmod_b, hmod_v] + exact (uint256_signextend_val_eq_uint256_signextend + (byteIdx % Compiler.Constants.evmModulus) (value % Compiler.Constants.evmModulus) hb hv).symm + +@[simp] theorem evalPureBuiltinViaEvmYulLean_and_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "and" [a, b] = + some ((a % Compiler.Constants.evmModulus) &&& (b % Compiler.Constants.evmModulus)) := by + rw [← uint256_size_eq_evmModulus] + change some (((Nat.bitwise Bool.and (a % EvmYul.UInt256.size) (b % EvmYul.UInt256.size)) % + EvmYul.UInt256.size)) = + some (Nat.bitwise Bool.and (a % EvmYul.UInt256.size) (b % EvmYul.UInt256.size)) + congr 1 + rw [Nat.mod_eq_of_lt] + exact Nat.bitwise_lt_two_pow (f := Bool.and) (n := 256) + (by simpa [EvmYul.UInt256.size] using Nat.mod_lt a (by decide : 0 < EvmYul.UInt256.size)) + (by simpa [EvmYul.UInt256.size] using Nat.mod_lt b (by decide : 0 < EvmYul.UInt256.size)) + +@[simp] theorem evalPureBuiltinViaEvmYulLean_or_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "or" [a, b] = + some ((a % Compiler.Constants.evmModulus) ||| (b % Compiler.Constants.evmModulus)) := by + rw [← uint256_size_eq_evmModulus] + change some (((Nat.bitwise Bool.or (a % EvmYul.UInt256.size) (b % EvmYul.UInt256.size)) % + EvmYul.UInt256.size)) = + some (Nat.bitwise Bool.or (a % EvmYul.UInt256.size) (b % EvmYul.UInt256.size)) + congr 1 + rw [Nat.mod_eq_of_lt] + exact Nat.bitwise_lt_two_pow (f := Bool.or) (n := 256) + (word_lt_uint256_size a) (word_lt_uint256_size b) + +@[simp] theorem evalPureBuiltinViaEvmYulLean_xor_native (a b : Nat) : + evalPureBuiltinViaEvmYulLean "xor" [a, b] = + some (Nat.xor (a % Compiler.Constants.evmModulus) (b % Compiler.Constants.evmModulus)) := by + rw [← uint256_size_eq_evmModulus] + change some (((a % EvmYul.UInt256.size ^^^ b % EvmYul.UInt256.size) % + EvmYul.UInt256.size)) = + some (a % EvmYul.UInt256.size ^^^ b % EvmYul.UInt256.size) + congr 1 + rw [Nat.mod_eq_of_lt] + exact Nat.xor_lt_two_pow (word_lt_uint256_size a) (word_lt_uint256_size b) + +private theorem xor_all_ones_uint256_word (a : Nat) : + (a % EvmYul.UInt256.size) ^^^ (EvmYul.UInt256.size - 1) = + EvmYul.UInt256.size - 1 - (a % EvmYul.UInt256.size) := by + calc + (a % EvmYul.UInt256.size) ^^^ (EvmYul.UInt256.size - 1) = + ((BitVec.ofNat 256 a) ^^^ BitVec.allOnes 256).toNat := by + simp [BitVec.toNat_xor, EvmYul.UInt256.size] + _ = (~~~(BitVec.ofNat 256 a)).toNat := by + rw [BitVec.xor_allOnes] + _ = EvmYul.UInt256.size - 1 - (a % EvmYul.UInt256.size) := by + simp [BitVec.toNat_not, EvmYul.UInt256.size] + +@[simp] theorem evalPureBuiltinViaEvmYulLean_not_native (a : Nat) : + evalPureBuiltinViaEvmYulLean "not" [a] = + some (Nat.xor (a % Compiler.Constants.evmModulus) + (Compiler.Constants.evmModulus - 1)) := by + rw [← uint256_size_eq_evmModulus] + change evalPureBuiltinViaEvmYulLean "not" [a] = + some ((a % EvmYul.UInt256.size) ^^^ (EvmYul.UInt256.size - 1)) + have hsub : evalPureBuiltinViaEvmYulLean "not" [a] = + some (EvmYul.UInt256.size - 1 - (a % EvmYul.UInt256.size)) := by + change evalPureBuiltinViaEvmYulLean "sub" [EvmYul.UInt256.size - 1, a] = + some (EvmYul.UInt256.size - 1 - (a % EvmYul.UInt256.size)) + rw [evalPureBuiltinViaEvmYulLean_sub_native] + rw [← uint256_size_eq_evmModulus] + have hs : 0 < EvmYul.UInt256.size := by simp [EvmYul.UInt256.size] + have ha : a % EvmYul.UInt256.size < EvmYul.UInt256.size := Nat.mod_lt _ hs + have hlt : EvmYul.UInt256.size - 1 - (a % EvmYul.UInt256.size) < EvmYul.UInt256.size := by + omega + have hmod : + ((EvmYul.UInt256.size + (EvmYul.UInt256.size - 1) % EvmYul.UInt256.size - + a % EvmYul.UInt256.size) % EvmYul.UInt256.size) = + EvmYul.UInt256.size - 1 - (a % EvmYul.UInt256.size) := by + have hsizeMinusOneMod : + (EvmYul.UInt256.size - 1) % EvmYul.UInt256.size = EvmYul.UInt256.size - 1 := by + exact Nat.mod_eq_of_lt (by omega) + rw [hsizeMinusOneMod] + have harr : + EvmYul.UInt256.size + (EvmYul.UInt256.size - 1) - a % EvmYul.UInt256.size = + EvmYul.UInt256.size + + (EvmYul.UInt256.size - 1 - (a % EvmYul.UInt256.size)) := by + omega + rw [harr, Nat.add_mod_left, Nat.mod_eq_of_lt hlt] + exact congrArg some hmod + rw [hsub] + simp [xor_all_ones_uint256_word] + +@[simp] theorem evalPureBuiltinViaEvmYulLean_shl_native (shift value : Nat) : + evalPureBuiltinViaEvmYulLean "shl" [shift, value] = + some (if shift % Compiler.Constants.evmModulus < 256 then + ((value % Compiler.Constants.evmModulus) * + 2 ^ (shift % Compiler.Constants.evmModulus)) % Compiler.Constants.evmModulus + else + 0) := by + rw [← uint256_size_eq_evmModulus] + change some (EvmYul.UInt256.toNat + (EvmYul.UInt256.shiftLeft (EvmYul.UInt256.ofNat value) (EvmYul.UInt256.ofNat shift))) = + some (if shift % EvmYul.UInt256.size < 256 then + ((value % EvmYul.UInt256.size) * 2 ^ (shift % EvmYul.UInt256.size)) % + EvmYul.UInt256.size + else + 0) + by_cases hs : shift % EvmYul.UInt256.size < 256 + · have hs' : ¬ 256 ≤ (EvmYul.UInt256.ofNat shift).val := by + change ¬ 256 ≤ shift % EvmYul.UInt256.size + exact Nat.not_le_of_lt hs + simp [hs, EvmYul.UInt256.shiftLeft, EvmYul.UInt256.toNat, hs', Nat.shiftLeft_eq] + change (value % EvmYul.UInt256.size) * 2 ^ (shift % EvmYul.UInt256.size) % + EvmYul.UInt256.size = + value * 2 ^ (shift % EvmYul.UInt256.size) % EvmYul.UInt256.size + rw [Nat.mul_mod, Nat.mul_mod] + simp + · have hs' : 256 ≤ (EvmYul.UInt256.ofNat shift).val := by + change 256 ≤ shift % EvmYul.UInt256.size + exact Nat.not_lt.mp hs + simp [hs, EvmYul.UInt256.shiftLeft, EvmYul.UInt256.toNat, hs'] + +@[simp] theorem evalPureBuiltinViaEvmYulLean_shr_native (shift value : Nat) : + evalPureBuiltinViaEvmYulLean "shr" [shift, value] = + some (if shift % Compiler.Constants.evmModulus < 256 then + (value % Compiler.Constants.evmModulus) / + 2 ^ (shift % Compiler.Constants.evmModulus) + else + 0) := by + rw [← uint256_size_eq_evmModulus] + change some (EvmYul.UInt256.toNat + (EvmYul.UInt256.shiftRight (EvmYul.UInt256.ofNat value) (EvmYul.UInt256.ofNat shift))) = + some (if shift % EvmYul.UInt256.size < 256 then + (value % EvmYul.UInt256.size) / 2 ^ (shift % EvmYul.UInt256.size) + else + 0) + by_cases hs : shift % EvmYul.UInt256.size < 256 + · have hs' : ¬ 256 ≤ (EvmYul.UInt256.ofNat shift).val := by + change ¬ 256 ≤ shift % EvmYul.UInt256.size + exact Nat.not_le_of_lt hs + simp [hs, EvmYul.UInt256.shiftRight, EvmYul.UInt256.toNat, hs', Nat.shiftRight_eq_div_pow] + change value % EvmYul.UInt256.size / 2 ^ (shift % EvmYul.UInt256.size) = + value % EvmYul.UInt256.size / 2 ^ (shift % EvmYul.UInt256.size) + rfl + · have hs' : 256 ≤ (EvmYul.UInt256.ofNat shift).val := by + change 256 ≤ shift % EvmYul.UInt256.size + exact Nat.not_lt.mp hs + simp [hs, EvmYul.UInt256.shiftRight, EvmYul.UInt256.toNat, hs'] + +end Compiler.Proofs.YulGeneration.Backends diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean index 94acc32b2..1be82e566 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean @@ -1,22 +1,21 @@ /- Phase 4: Retarget the theorem stack to EVMYulLean. - This module proves that the Verity Yul semantics — currently targeting the - `.verity` builtin backend — are equivalent to execution under the `.evmYulLean` - backend for programs that use only bridged builtins. + This module proves that the legacy Verity builtin backend and the + `.evmYulLean` builtin backend are equivalent for programs that use only + bridged builtins. - **Key theorem**: `backends_agree_on_bridged_builtins` shows that + **Key transition theorem**: the file-local + `backends_agree_on_bridged_builtins` shows that `evalBuiltinCallWithBackendContext .verity ... func args = evalBuiltinCallWithBackendContext .evmYulLean ... func args` for every `func ∈ bridgedBuiltins`. - This module also proves the expression-level lift for `BridgedExpr`: - `evalYulExpr_evmYulLean_eq_on_bridged`, plus the recursive target lift - `execYulFuelWithBackend_eq_on_bridged_target` for `BridgedTarget` - executions. The Layer-3 runtime-code lift in this module remains parameterized - by embedded-body `BridgedStmts` witnesses; `EvmYulLeanBodyClosure.lean` and - `EndToEnd.lean` discharge those witnesses for the supported safe source-body - fragment. + This module also proves file-local expression and recursive target lifts for + `BridgedExpr` and `BridgedTarget` executions. The Layer-3 runtime-code lift + remains parameterized by embedded-body `BridgedStmts` witnesses; + `EvmYulLeanBodyClosure.lean` and `EndToEnd.lean` discharge those witnesses for + the supported safe source-body fragment. **Trust boundary shift (pointwise)**: For any builtin call using a bridged name, the trust boundary moves from "Verity's custom Yul builtin semantics @@ -28,8 +27,11 @@ Run: lake build Compiler.Proofs.YulGeneration.Backends.EvmYulLeanRetarget -/ +import Compiler.Codegen +import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgePredicates import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeLemmas -import Compiler.Proofs.YulGeneration.Preservation +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanPureBuiltinLemmas namespace Compiler.Proofs.YulGeneration.Backends @@ -46,7 +48,7 @@ The proof strategy: 3. Right arity: apply the context-lifted bridge lemma from `EvmYulLeanBridgeLemmas` 4. Wrong arity: both sides are definitionally equal (`rfl`) -This avoids unfolding the expensive `evalBuiltinCallWithContext` if-chain. -/ +This avoids unfolding the expensive `legacyEvalBuiltinCallWithContext` if-chain. -/ -- Binary builtins: argVals matches [a, b] private theorem backends_agree_add s se mv ta bt bn ci bb sl cd av : @@ -328,7 +330,7 @@ private theorem backends_agree_calldatasize s se mv ta bt bn ci bb sl cd av : | _ :: _ => rfl -- Unary builtin: sload (state-dependent, routed through the same --- `storage : IRStorageSlot → IRStorageWord` lookup used by Verity's `evalBuiltinCallWithContext`) +-- `storage : IRStorageSlot → IRStorageWord` lookup used by Verity's `legacyEvalBuiltinCallWithContext`) private theorem backends_agree_sload s se mv ta bt bn ci bb sl cd av : evalBuiltinCallWithBackendContext .verity s se mv ta bt bn ci bb sl cd "sload" av = evalBuiltinCallWithBackendContext .evmYulLean s se mv ta bt bn ci bb sl cd "sload" av := by @@ -362,12 +364,12 @@ All bridged builtin dependencies are fully proven in `EvmYulLeanBridgeLemmas.lea This is the master backend equivalence theorem for Phase 4 retargeting. It composes the 36 per-builtin bridge theorems into a single dispatch proof. - Every builtin handled by `evalBuiltinCallWithContext` is now bridged, so + Every builtin handled by `legacyEvalBuiltinCallWithContext` is now bridged, so `unbridgedBuiltins` is empty. This theorem is sorry-free, composing the fully proven per-builtin bridge lemmas in `EvmYulLeanBridgeLemmas.lean`. -/ -theorem backends_agree_on_bridged_builtins +private theorem backends_agree_on_bridged_builtins (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) (func : String) (argVals : List Nat) @@ -426,11 +428,8 @@ only bridged builtin names, plus the backend-independent `tload`/`mload` special cases handled directly by the Verity Yul expression evaluator. -/ -def allowedExprCallName (func : String) : Prop := - func ∈ bridgedBuiltins ∨ func = "tload" ∨ func = "mload" ∨ func = "keccak256" - set_option maxHeartbeats 1000000 in -/-- `keccak256` is not handled by Verity's `evalBuiltinCallWithContext` (it +/-- `keccak256` is not handled by Verity's `legacyEvalBuiltinCallWithContext` (it falls through the 35-case if-else chain to the final `else none`) and is not handled by the EVMYulLean adapter (`evalBuiltinCallViaEvmYulLean` and `evalPureBuiltinViaEvmYulLean` both default to `none` for unknown funcs). @@ -452,19 +451,9 @@ private theorem backends_agree_on_keccak256 -- simplest path; targeted simp at every level would be longer and no faster. rfl -inductive BridgedExpr : Compiler.Yul.YulExpr → Prop - | lit (n : Nat) : BridgedExpr (.lit n) - | hex (n : Nat) : BridgedExpr (.hex n) - | str (s : String) : BridgedExpr (.str s) - | ident (name : String) : BridgedExpr (.ident name) - | call (func : String) (args : List Compiler.Yul.YulExpr) - (hName : allowedExprCallName func) - (hArgs : ∀ arg ∈ args, BridgedExpr arg) : - BridgedExpr (.call func args) - mutual -def evalYulExprsWithBackend (backend : BuiltinBackend) (state : YulState) : +private def evalYulExprsWithBackend (backend : BuiltinBackend) (state : YulState) : List Compiler.Yul.YulExpr → Option (List Nat) | [] => some [] | e :: es => do @@ -477,7 +466,7 @@ decreasing_by simp [exprsSize] omega -def evalYulCallWithBackend (backend : BuiltinBackend) (state : YulState) +private def evalYulCallWithBackend (backend : BuiltinBackend) (state : YulState) (func : String) : List Compiler.Yul.YulExpr → Option Nat | args => do let argVals ← evalYulExprsWithBackend backend state args @@ -501,7 +490,7 @@ termination_by args => exprsSize args + 1 decreasing_by omega -def evalYulExprWithBackend (backend : BuiltinBackend) (state : YulState) : +private def evalYulExprWithBackend (backend : BuiltinBackend) (state : YulState) : Compiler.Yul.YulExpr → Option Nat | .lit n => some n | .hex n => some n @@ -516,9 +505,9 @@ end mutual -private theorem evalYulExprWithBackend_verity_eq +private theorem evalYulExprWithBackend_evmYulLean_eq (state : YulState) (expr : Compiler.Yul.YulExpr) : - evalYulExprWithBackend .verity state expr = evalYulExpr state expr := by + evalYulExprWithBackend .evmYulLean state expr = evalYulExpr state expr := by cases expr with | lit _ => simp [evalYulExprWithBackend, evalYulExpr] | hex _ => simp [evalYulExprWithBackend, evalYulExpr] @@ -526,24 +515,24 @@ private theorem evalYulExprWithBackend_verity_eq | ident _ => simp [evalYulExprWithBackend, evalYulExpr] | call func args => simp only [evalYulExprWithBackend, evalYulExpr, evalYulCallWithBackend, evalYulCall] - rw [evalYulExprsWithBackend_verity_eq state args] + rw [evalYulExprsWithBackend_evmYulLean_eq state args] rfl -private theorem evalYulExprsWithBackend_verity_eq +private theorem evalYulExprsWithBackend_evmYulLean_eq (state : YulState) (args : List Compiler.Yul.YulExpr) : - evalYulExprsWithBackend .verity state args = evalYulExprs state args := by + evalYulExprsWithBackend .evmYulLean state args = evalYulExprs state args := by cases args with | nil => simp [evalYulExprsWithBackend, evalYulExprs] | cons arg rest => simp only [evalYulExprsWithBackend, evalYulExprs] - rw [evalYulExprWithBackend_verity_eq state arg, - evalYulExprsWithBackend_verity_eq state rest] + rw [evalYulExprWithBackend_evmYulLean_eq state arg, + evalYulExprsWithBackend_evmYulLean_eq state rest] end mutual -theorem evalYulExprWithBackend_eq_on_bridged +private theorem evalYulExprWithBackend_eq_on_bridged (state : YulState) (expr : Compiler.Yul.YulExpr) (hExpr : BridgedExpr expr) : evalYulExprWithBackend .verity state expr = evalYulExprWithBackend .evmYulLean state expr := by @@ -589,17 +578,15 @@ private theorem evalYulExprsWithBackend_eq_on_bridged end -theorem evalYulExpr_evmYulLean_eq_on_bridged - (state : YulState) (expr : Compiler.Yul.YulExpr) (hExpr : BridgedExpr expr) : +private theorem evalYulExpr_evmYulLean_eq_on_bridged + (state : YulState) (expr : Compiler.Yul.YulExpr) (_hExpr : BridgedExpr expr) : evalYulExpr state expr = evalYulExprWithBackend .evmYulLean state expr := by - have h := evalYulExprWithBackend_eq_on_bridged state expr hExpr - rw [← evalYulExprWithBackend_verity_eq state expr] - exact h + exact (evalYulExprWithBackend_evmYulLean_eq state expr).symm /-! ## Statement-level backend-parameterized executor -`execYulFuelWithBackend` mirrors `execYulFuel` from `Semantics.lean` but routes +`execYulFuelWithBackend` mirrors `legacyExecYulFuel` from `Semantics.lean` but routes each expression evaluation through `evalYulExprWithBackend backend`. The statement and runtime-code theorems below bridge `.verity` and `.evmYulLean` on targets satisfying the `Bridged*` predicates. Source-body closure and the @@ -607,7 +594,7 @@ public safe-body EndToEnd wrapper live in `EvmYulLeanBodyClosure.lean` and `Compiler.Proofs.EndToEnd`. -/ -def execYulFuelWithBackend (backend : BuiltinBackend) : +private def execYulFuelWithBackend (backend : BuiltinBackend) : Nat → YulState → YulExecTarget → YulExecResult | _, state, .stmts [] => .continue state | _, state, .stmt (Compiler.Yul.YulStmt.funcDef _ _ _ _) => .continue state @@ -738,15 +725,15 @@ def execYulFuelWithBackend (backend : BuiltinBackend) : | .stop s => .stop s | .revert s => .revert s -/-- The backend-parameterized executor recovers `execYulFuel` at the `.verity` +/-- The backend-parameterized executor recovers `legacyExecYulFuel` at the `.verity` backend. Statement-level analogue of `evalYulExprWithBackend_verity_eq` — this is the correctness obligation that justifies replacing every - `execYulFuel` call in upstream theorems with + `legacyExecYulFuel` call in upstream theorems with `execYulFuelWithBackend .verity`. -/ -theorem execYulFuelWithBackend_verity_eq +private theorem execYulFuelWithBackend_evmYulLean_eq (fuel : Nat) (state : YulState) (target : YulExecTarget) : - execYulFuelWithBackend .verity fuel state target = - execYulFuel fuel state target := by + execYulFuelWithBackend .evmYulLean fuel state target = + legacyExecYulFuel fuel state target := by induction fuel generalizing state target with | zero => cases target with @@ -758,15 +745,15 @@ theorem execYulFuelWithBackend_verity_eq cases s <;> ( try rfl all_goals ( - simp only [execYulFuelWithBackend, execYulFuel, - evalYulExprWithBackend_verity_eq, - evalYulExprsWithBackend_verity_eq, ih] + simp only [execYulFuelWithBackend, legacyExecYulFuel, + evalYulExprWithBackend_evmYulLean_eq, + evalYulExprsWithBackend_evmYulLean_eq, ih] try rfl)) | stmts ss => cases ss <;> ( try rfl all_goals ( - simp only [execYulFuelWithBackend, execYulFuel, ih] + simp only [execYulFuelWithBackend, legacyExecYulFuel, ih] try rfl)) /-! ## Statement-level backend equivalence: value-binding helpers @@ -782,7 +769,7 @@ These are intentionally narrow helpers. A future statement-level predicate them rather than re-deriving the expression rewrite each time. -/ -theorem execYulFuelWithBackend_let_eq_on_bridged +private theorem execYulFuelWithBackend_let_eq_on_bridged (fuel : Nat) (state : YulState) (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) : execYulFuelWithBackend .verity fuel state (.stmt (.let_ name value)) = @@ -793,7 +780,7 @@ theorem execYulFuelWithBackend_let_eq_on_bridged simp only [execYulFuelWithBackend] rw [evalYulExprWithBackend_eq_on_bridged state value hValue] -theorem execYulFuelWithBackend_assign_eq_on_bridged +private theorem execYulFuelWithBackend_assign_eq_on_bridged (fuel : Nat) (state : YulState) (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) : execYulFuelWithBackend .verity fuel state (.stmt (.assign name value)) = @@ -813,168 +800,6 @@ control flow (`switch`, `for`, recursive `block`) still needs a separate fuel/AST induction. -/ -inductive BridgedStraightStmt : Compiler.Yul.YulStmt → Prop - | comment (text : String) : BridgedStraightStmt (.comment text) - | let_ (name : String) (value : Compiler.Yul.YulExpr) - (hValue : BridgedExpr value) : - BridgedStraightStmt (.let_ name value) - | letMany (names : List String) (value : Compiler.Yul.YulExpr) : - BridgedStraightStmt (.letMany names value) - | assign (name : String) (value : Compiler.Yul.YulExpr) - (hValue : BridgedExpr value) : - BridgedStraightStmt (.assign name value) - | leave : BridgedStraightStmt .leave - | expr_sstore_mapping (baseExpr keyExpr valExpr : Compiler.Yul.YulExpr) - (hBase : BridgedExpr baseExpr) (hKey : BridgedExpr keyExpr) - (hVal : BridgedExpr valExpr) : - BridgedStraightStmt - (.expr (.call "sstore" [.call "mappingSlot" [baseExpr, keyExpr], valExpr])) - /-- `sstore(lit slot, valExpr)` for a literal slot. Covers the common - direct-storage-write shape emitted by `compileSetStorage` for unpacked - single-slot fields at a known slot index. The executor's inner match on - `.lit slot` falls through to the generic `sstore` branch (it is not a - `mappingSlot` call), which only differs between backends via - `evalYulExprWithBackend` on `.lit slot` / `valExpr` — both bridged. -/ - | expr_sstore_lit (slot : Nat) (valExpr : Compiler.Yul.YulExpr) - (hVal : BridgedExpr valExpr) : - BridgedStraightStmt (.expr (.call "sstore" [.lit slot, valExpr])) - /-- `sstore(ident slotName, valExpr)` for compiler-emitted writes whose - storage slot has already been bound to a local variable, e.g. struct-member - and compatibility write helpers. -/ - | expr_sstore_ident (slotName : String) (valExpr : Compiler.Yul.YulExpr) - (hVal : BridgedExpr valExpr) : - BridgedStraightStmt (.expr (.call "sstore" [.ident slotName, valExpr])) - /-- `sstore(add(leftExpr, rightExpr), valExpr)` for storage-array element - writes where the slot is computed as `base + index`. The executor's inner - match on `.call "add" [...]` falls through to the generic `sstore` branch - (it is not a `mappingSlot` call), so both backends only diverge on - `evalYulExprWithBackend` for the `add` subexpression and the value — both - bridged (`add` is in `bridgedBuiltins`). Covers the compile paths used by - `compileStorageArrayPush`, `compileStorageArrayPop`, and - `compileSetStorageArrayElement`. -/ - | expr_sstore_add (leftExpr rightExpr valExpr : Compiler.Yul.YulExpr) - (hLeft : BridgedExpr leftExpr) (hRight : BridgedExpr rightExpr) - (hVal : BridgedExpr valExpr) : - BridgedStraightStmt - (.expr (.call "sstore" - [.call "add" [leftExpr, rightExpr], valExpr])) - | expr_mstore (offsetExpr valExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : - BridgedStraightStmt (.expr (.call "mstore" [offsetExpr, valExpr])) - | expr_tstore (offsetExpr valExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : - BridgedStraightStmt (.expr (.call "tstore" [offsetExpr, valExpr])) - | expr_stop : BridgedStraightStmt (.expr (.call "stop" [])) - | expr_return (offsetExpr sizeExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : - BridgedStraightStmt (.expr (.call "return" [offsetExpr, sizeExpr])) - | expr_revert (offsetExpr sizeExpr : Compiler.Yul.YulExpr) : - BridgedStraightStmt (.expr (.call "revert" [offsetExpr, sizeExpr])) - /-- `logN(args...)` for `N ∈ {0,1,2,3,4}`. The Yul semantics dispatches log - calls via backend-agnostic `applyYulLogCall?` (takes only state + func + - evaluated argument values), so both backends diverge only on the argument - evaluation step which is closed by `BridgedExpr` on each argument. -/ - | expr_log (func : String) (args : List Compiler.Yul.YulExpr) - (hLog : isYulLogName func = true) - (hArgs : ∀ arg ∈ args, BridgedExpr arg) : - BridgedStraightStmt (.expr (.call func args)) - | funcDef (name : String) (params rets : List String) - (body : List Compiler.Yul.YulStmt) : - BridgedStraightStmt (.funcDef name params rets body) - -def BridgedStraightStmts (stmts : List Compiler.Yul.YulStmt) : Prop := - ∀ stmt ∈ stmts, BridgedStraightStmt stmt - -/-! ### List-level convenience helpers for `BridgedStraightStmts` - -Analogues of `BridgedStmts_nil`/`_cons`/`_append` (defined further below for -the recursive `BridgedStmt` predicate) so that callers composing scalar-event -emission fragments or other compiler-emitted concatenated straight-line lists -can piece them together without unfolding the membership definition at each -call site. -/ - -theorem BridgedStraightStmts_nil : BridgedStraightStmts [] := by - intro stmt hMem - cases hMem - -theorem BridgedStraightStmts_cons {stmt : Compiler.Yul.YulStmt} - {stmts : List Compiler.Yul.YulStmt} - (hStmt : BridgedStraightStmt stmt) (hStmts : BridgedStraightStmts stmts) : - BridgedStraightStmts (stmt :: stmts) := by - intro s hMem - cases hMem with - | head => exact hStmt - | tail _ hTail => exact hStmts s hTail - -theorem BridgedStraightStmts_append {xs ys : List Compiler.Yul.YulStmt} - (hXs : BridgedStraightStmts xs) (hYs : BridgedStraightStmts ys) : - BridgedStraightStmts (xs ++ ys) := by - intro stmt hMem - simp only [List.mem_append] at hMem - cases hMem with - | inl h => exact hXs stmt h - | inr h => exact hYs stmt h - -theorem BridgedStraightStmts_singleton {stmt : Compiler.Yul.YulStmt} - (hStmt : BridgedStraightStmt stmt) : BridgedStraightStmts [stmt] := - BridgedStraightStmts_cons hStmt BridgedStraightStmts_nil - -/-- Snoc composition for `BridgedStraightStmts`: append a single - `BridgedStraightStmt` to the end of an already-bridged straight list. - Parallels `BridgedStmts_snoc` for the straight-line layer, saving an - explicit `BridgedStraightStmts_singleton` wrap when chaining - `BridgedStraightStmts_append xs (BridgedStraightStmts_singleton y)`. -/ -theorem BridgedStraightStmts_snoc {xs : List Compiler.Yul.YulStmt} - {y : Compiler.Yul.YulStmt} - (hXs : BridgedStraightStmts xs) (hY : BridgedStraightStmt y) : - BridgedStraightStmts (xs ++ [y]) := - BridgedStraightStmts_append hXs (BridgedStraightStmts_singleton hY) - -/-- A list of `(offset, value)` expression pairs where each component is a - `BridgedExpr` maps to a `BridgedStraightStmts` list of `mstore(offset, - value)` statements. Directly supports the scalar event-emission compiler - pattern where `sigStores` and `unindexedStores` are both computed as - `List YulStmt` via `.map` over pair-shaped data. -/ -theorem BridgedStraightStmts_map_mstore - (pairs : List (Compiler.Yul.YulExpr × Compiler.Yul.YulExpr)) - (hPairs : ∀ p ∈ pairs, BridgedExpr p.1 ∧ BridgedExpr p.2) : - BridgedStraightStmts - (pairs.map fun p => - Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "mstore" [p.1, p.2])) := by - induction pairs with - | nil => exact BridgedStraightStmts_nil - | cons p rest ih => - have hHead : BridgedExpr p.1 ∧ BridgedExpr p.2 := hPairs p (by simp) - have hRest : ∀ q ∈ rest, BridgedExpr q.1 ∧ BridgedExpr q.2 := by - intro q hq - exact hPairs q (by simp [hq]) - exact BridgedStraightStmts_cons - (BridgedStraightStmt.expr_mstore p.1 p.2 hHead.1 hHead.2) - (ih hRest) - -/-- Analogue of `BridgedStraightStmts_map_mstore` for the transient-store - variant. Compiler helpers that target transient storage (EIP-1153) - occasionally emit concatenated `tstore` fragments, and having the - `map`-shaped helper pre-proved avoids per-fragment list recursion. -/ -theorem BridgedStraightStmts_map_tstore - (pairs : List (Compiler.Yul.YulExpr × Compiler.Yul.YulExpr)) - (hPairs : ∀ p ∈ pairs, BridgedExpr p.1 ∧ BridgedExpr p.2) : - BridgedStraightStmts - (pairs.map fun p => - Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "tstore" [p.1, p.2])) := by - induction pairs with - | nil => exact BridgedStraightStmts_nil - | cons p rest ih => - have hHead : BridgedExpr p.1 ∧ BridgedExpr p.2 := hPairs p (by simp) - have hRest : ∀ q ∈ rest, BridgedExpr q.1 ∧ BridgedExpr q.2 := by - intro q hq - exact hPairs q (by simp [hq]) - exact BridgedStraightStmts_cons - (BridgedStraightStmt.expr_tstore p.1 p.2 hHead.1 hHead.2) - (ih hRest) - private theorem execYulFuelWithBackend_eq_on_bridged_straight_stmt (fuel : Nat) (state : YulState) (stmt : Compiler.Yul.YulStmt) (hStmt : BridgedStraightStmt stmt) : @@ -1077,7 +902,7 @@ private theorem execYulFuelWithBackend_eq_on_bridged_straight_stmt simp [execYulFuelWithBackend, isYulLogName, hEval] | funcDef _ _ _ _ => cases fuel <;> rfl -theorem execYulFuelWithBackend_eq_on_bridged_straight_stmts +private theorem execYulFuelWithBackend_eq_on_bridged_straight_stmts (fuel : Nat) (state : YulState) (stmts : List Compiler.Yul.YulStmt) (hStmts : BridgedStraightStmts stmts) : execYulFuelWithBackend .verity fuel state (.stmts stmts) = @@ -1108,7 +933,7 @@ theorem execYulFuelWithBackend_eq_on_bridged_straight_stmts the block constructor when the block body is already in the straight-line fragment; recursive blocks and branching control flow still require the broader statement predicate/induction. -/ -theorem execYulFuelWithBackend_block_eq_on_bridged_straight_stmts +private theorem execYulFuelWithBackend_block_eq_on_bridged_straight_stmts (fuel : Nat) (state : YulState) (stmts : List Compiler.Yul.YulStmt) (hStmts : BridgedStraightStmts stmts) : execYulFuelWithBackend .verity fuel state (.stmt (.block stmts)) = @@ -1126,7 +951,7 @@ theorem execYulFuelWithBackend_block_eq_on_bridged_straight_stmts First narrow-helper lift into branching control flow; `.switch` and `.for_` still require their own helpers, and recursive control-flow bodies still require a broader predicate/induction. -/ -theorem execYulFuelWithBackend_if_eq_on_bridged_body +private theorem execYulFuelWithBackend_if_eq_on_bridged_body (fuel : Nat) (state : YulState) (cond : Compiler.Yul.YulExpr) (body : List Compiler.Yul.YulStmt) (hCond : BridgedExpr cond) (hBody : BridgedStraightStmts body) : @@ -1145,17 +970,12 @@ theorem execYulFuelWithBackend_if_eq_on_bridged_body · simp [hv] exact execYulFuelWithBackend_eq_on_bridged_straight_stmts fuel state body hBody -def BridgedSwitchCases (cases : List (Nat × List Compiler.Yul.YulStmt)) : Prop := - ∀ scrutinee value body, - cases.find? (fun x => decide (x.fst = scrutinee)) = some (value, body) → - BridgedStraightStmts body - /-- A `.switch` with a bridged scrutinee and straight-line selected bodies preserves backend equivalence. The predicate only needs to cover bodies that can actually be selected by `find?`; the default branch is handled separately. Recursive switch bodies and loops still need the broader statement predicate/induction. -/ -theorem execYulFuelWithBackend_switch_eq_on_bridged_cases +private theorem execYulFuelWithBackend_switch_eq_on_bridged_cases (fuel : Nat) (state : YulState) (expr : Compiler.Yul.YulExpr) (cases : List (Nat × List Compiler.Yul.YulStmt)) (defaultCase : Option (List Compiler.Yul.YulStmt)) @@ -1192,7 +1012,7 @@ theorem execYulFuelWithBackend_switch_eq_on_bridged_cases the predecessor fuel with an empty initializer, so the proof follows the executor's fuel structure directly. Recursive control-flow inside the loop lists still needs the broader statement predicate/induction. -/ -theorem execYulFuelWithBackend_for_eq_on_bridged_parts +private theorem execYulFuelWithBackend_for_eq_on_bridged_parts (fuel : Nat) (state : YulState) (init : List Compiler.Yul.YulStmt) (cond : Compiler.Yul.YulExpr) (post body : List Compiler.Yul.YulStmt) @@ -1242,39 +1062,7 @@ expression dependency must satisfy `BridgedExpr`, and every nested statement list must recursively satisfy `BridgedStmt`. -/ -inductive BridgedStmt : Compiler.Yul.YulStmt → Prop - | straight (stmt : Compiler.Yul.YulStmt) - (hStmt : BridgedStraightStmt stmt) : - BridgedStmt stmt - | block (stmts : List Compiler.Yul.YulStmt) - (hStmts : ∀ stmt ∈ stmts, BridgedStmt stmt) : - BridgedStmt (.block stmts) - | if_ (cond : Compiler.Yul.YulExpr) (body : List Compiler.Yul.YulStmt) - (hCond : BridgedExpr cond) - (hBody : ∀ stmt ∈ body, BridgedStmt stmt) : - BridgedStmt (.if_ cond body) - | «switch» (expr : Compiler.Yul.YulExpr) - (cases : List (Nat × List Compiler.Yul.YulStmt)) - (defaultCase : Option (List Compiler.Yul.YulStmt)) - (hExpr : BridgedExpr expr) - (hCases : ∀ scrutinee value body, - cases.find? (fun x => decide (x.fst = scrutinee)) = some (value, body) → - ∀ stmt ∈ body, BridgedStmt stmt) - (hDefault : ∀ body, defaultCase = some body → - ∀ stmt ∈ body, BridgedStmt stmt) : - BridgedStmt (.switch expr cases defaultCase) - | for_ (init : List Compiler.Yul.YulStmt) (cond : Compiler.Yul.YulExpr) - (post body : List Compiler.Yul.YulStmt) - (hInit : ∀ stmt ∈ init, BridgedStmt stmt) - (hCond : BridgedExpr cond) - (hPost : ∀ stmt ∈ post, BridgedStmt stmt) - (hBody : ∀ stmt ∈ body, BridgedStmt stmt) : - BridgedStmt (.for_ init cond post body) - -def BridgedStmts (stmts : List Compiler.Yul.YulStmt) : Prop := - ∀ stmt ∈ stmts, BridgedStmt stmt - -inductive BridgedTarget : YulExecTarget → Prop +private inductive BridgedTarget : YulExecTarget → Prop | stmt (stmt : Compiler.Yul.YulStmt) (hStmt : BridgedStmt stmt) : BridgedTarget (.stmt stmt) | stmts (stmts : List Compiler.Yul.YulStmt) (hStmts : BridgedStmts stmts) : @@ -1289,44 +1077,6 @@ selector switch, fallback/receive wrapper, optional mapping helper) is bridged whenever the IR function and entrypoint bodies it contains are bridged. -/ -theorem BridgedStmts_nil : BridgedStmts [] := by - intro stmt hMem - cases hMem - -theorem BridgedStmts_cons {stmt : Compiler.Yul.YulStmt} - {stmts : List Compiler.Yul.YulStmt} - (hStmt : BridgedStmt stmt) (hStmts : BridgedStmts stmts) : - BridgedStmts (stmt :: stmts) := by - intro s hMem - cases hMem with - | head => exact hStmt - | tail _ hTail => exact hStmts s hTail - -theorem BridgedStmts_append {xs ys : List Compiler.Yul.YulStmt} - (hXs : BridgedStmts xs) (hYs : BridgedStmts ys) : - BridgedStmts (xs ++ ys) := by - intro stmt hMem - simp only [List.mem_append] at hMem - cases hMem with - | inl h => exact hXs stmt h - | inr h => exact hYs stmt h - -/-- Public singleton helper: if `hStmt : BridgedStmt stmt` then the one-element - list `[stmt]` satisfies `BridgedStmts`. Matches `BridgedStraightStmts_singleton` - for list composition of recursive-statement lists. -/ -theorem BridgedStmts_singleton {stmt : Compiler.Yul.YulStmt} - (hStmt : BridgedStmt stmt) : BridgedStmts [stmt] := - BridgedStmts_cons hStmt BridgedStmts_nil - -/-- Snoc composition: append a single `BridgedStmt` to the end of an - already-bridged list. Saves an explicit `BridgedStmts_singleton` wrap - when chaining `BridgedStmts_append xs (BridgedStmts_singleton y)`. -/ -theorem BridgedStmts_snoc {xs : List Compiler.Yul.YulStmt} - {y : Compiler.Yul.YulStmt} - (hXs : BridgedStmts xs) (hY : BridgedStmt y) : - BridgedStmts (xs ++ [y]) := - BridgedStmts_append hXs (BridgedStmts_singleton hY) - private theorem bridgedExpr_callvalue : BridgedExpr (Compiler.Yul.YulExpr.call "callvalue" []) := by exact BridgedExpr.call "callvalue" [] (Or.inl (by simp [bridgedBuiltins])) @@ -1354,19 +1104,56 @@ private theorem bridgedExpr_selector : exact BridgedExpr.lit 0 /-- The generated dispatcher selector expression is in the bridged expression -fragment, so the EVMYulLean-backed interpreter oracle evaluates it exactly like +fragment, so the EVMYulLean fuel wrapper evaluates it exactly like the historical Verity interpreter. -/ -theorem bridgedExpr_selectorExpr : +private theorem bridgedExpr_selectorExpr : BridgedExpr Compiler.Proofs.YulGeneration.selectorExpr := by simpa [Compiler.Proofs.YulGeneration.selectorExpr] using bridgedExpr_selector -/-- The EVMYulLean-backed interpreter oracle selects the same 4-byte dispatcher +set_option maxHeartbeats 1000000 in +@[simp] private theorem evalYulExpr_selectorExpr_semantics : + ∀ state : YulState, + evalYulExpr state Compiler.Proofs.YulGeneration.selectorExpr = + some (state.selector % selectorModulus) := by + intro state + have hShiftModEq : selectorShift % evmModulus = selectorShift := by + have hShiftLtModulus : selectorShift < evmModulus := by + norm_num [selectorShift, evmModulus] + exact Nat.mod_eq_of_lt hShiftLtModulus + have hSelectorShiftLt256 : selectorShift < 256 := by + norm_num [selectorShift] + have hSelectorShiftNotGe256 : ¬ 256 ≤ selectorShift := Nat.not_le_of_lt hSelectorShiftLt256 + have hSelectorWordLt : + (state.selector % selectorModulus) * 2 ^ selectorShift < evmModulus := by + have hModLt : state.selector % selectorModulus < selectorModulus := by + exact Nat.mod_lt _ (by decide) + have hPowPos : 0 < 2 ^ selectorShift := by + exact Nat.pow_pos (a := 2) (n := selectorShift) (by decide) + have hMulLt : + (state.selector % selectorModulus) * 2 ^ selectorShift < + selectorModulus * 2 ^ selectorShift := by + exact Nat.mul_lt_mul_of_pos_right hModLt hPowPos + have hModulusSplit : selectorModulus * 2 ^ selectorShift = evmModulus := by + norm_num [selectorModulus, selectorShift, evmModulus, Nat.pow_add, Nat.mul_comm, + Nat.mul_left_comm, Nat.mul_assoc] + simpa [hModulusSplit] using hMulLt + have hSelectorWordMod : + ((state.selector % selectorModulus) * 2 ^ selectorShift) % evmModulus = + (state.selector % selectorModulus) * 2 ^ selectorShift := by + exact Nat.mod_eq_of_lt hSelectorWordLt + simp [Compiler.Proofs.YulGeneration.selectorExpr, evalYulExpr, evalYulCall, evalYulExprs, + evalBuiltinCallWithBackendContext, Backends.evalBuiltinCallWithEvmYulLeanContext, + Backends.evalBuiltinCallViaEvmYulLean, + calldataloadWord, selectorWord, + hShiftModEq, hSelectorWordMod, hSelectorShiftNotGe256] + +/-- The EVMYulLean fuel wrapper selects the same 4-byte dispatcher selector as the generated Verity selector expression. This is the first generated-dispatcher semantic slice needed by the native -migration: every native/interpreter dispatcher simulation branches on this +migration: every native/EVMYulLean dispatcher simulation branches on this expression before it reaches storage, memory, or halt behavior. -/ -@[simp] theorem evalYulExprWithBackend_evmYulLean_selectorExpr_semantics +@[simp] private theorem evalYulExprWithBackend_evmYulLean_selectorExpr_semantics (state : YulState) : evalYulExprWithBackend .evmYulLean state Compiler.Proofs.YulGeneration.selectorExpr = @@ -1417,959 +1204,20 @@ private theorem bridgedExpr_iszero_ident (name : String) : subst hMem exact BridgedExpr.ident name -/-- `keccak256(offsetExpr, sizeExpr)` with bridged argument expressions is a - `BridgedExpr`. Both backends compute `abstractKeccakMemorySlice` directly - in `evalYulCallWithBackend` / `evalYulCall` after the PR #1732 proven-fragment - expansion, so this is a genuine convenience helper rather than an axiom - wrapper. Useful for closing event-emission bodies (scalar `emit` compiles - a `let __evt_topic0 := keccak256(__evt_ptr, sigBytes.length)` binding). -/ -theorem bridgedExpr_keccak256 (offsetExpr sizeExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : - BridgedExpr - (Compiler.Yul.YulExpr.call "keccak256" [offsetExpr, sizeExpr]) := by - refine BridgedExpr.call "keccak256" _ (Or.inr (Or.inr (Or.inr rfl))) ?_ - intro arg hMem - simp only [List.mem_cons, List.mem_nil_iff, or_false] at hMem - rcases hMem with rfl | rfl - · exact hOffset - · exact hSize - -/-- `mload(offsetExpr)` with a bridged `offsetExpr` is a `BridgedExpr`. Both - backends already include `mload` directly in `evalYulCallWithBackend` / - `evalYulCall` (single-slot memory read by Verity's free-memory model). - Useful for closing compiler-emitted `let __evt_ptr := mload(0x40)` shapes - at the head of scalar `emit` bodies, and for any prologue helper that - consults the free-memory pointer. -/ -theorem bridgedExpr_mload (offsetExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) : - BridgedExpr - (Compiler.Yul.YulExpr.call "mload" [offsetExpr]) := by - refine BridgedExpr.call "mload" _ (Or.inr (Or.inr (Or.inl rfl))) ?_ - intro arg hMem - simp only [List.mem_singleton] at hMem - subst hMem - exact hOffset - -/-- `tload(slotExpr)` analogue of `bridgedExpr_mload`. EIP-1153 transient - storage reads are in `allowedExprCallName` and share the same two-backend - `tload` branch in `evalYulCallWithBackend`. Having the helper available - keeps tload-consuming Yul prologues composable under `BridgedExpr`. -/ -theorem bridgedExpr_tload (slotExpr : Compiler.Yul.YulExpr) - (hSlot : BridgedExpr slotExpr) : - BridgedExpr - (Compiler.Yul.YulExpr.call "tload" [slotExpr]) := by - refine BridgedExpr.call "tload" _ (Or.inr (Or.inl rfl)) ?_ - intro arg hMem - simp only [List.mem_singleton] at hMem - subst hMem - exact hSlot - -/-- `let name := mload(offsetExpr)` with a bridged `offsetExpr` is a - `BridgedStraightStmt`. Composes `BridgedStraightStmt.let_` with - `bridgedExpr_mload`. Directly matches the `let __evt_ptr := mload(0x40)` - prologue emitted at the head of compiled scalar `emit` bodies. -/ -theorem bridgedStraightStmt_let_mload (name : String) - (offsetExpr : Compiler.Yul.YulExpr) (hOffset : BridgedExpr offsetExpr) : - BridgedStraightStmt - (.let_ name (Compiler.Yul.YulExpr.call "mload" [offsetExpr])) := - BridgedStraightStmt.let_ name _ (bridgedExpr_mload offsetExpr hOffset) - -/-- `let name := tload(slotExpr)` analogue of `bridgedStraightStmt_let_mload` - for EIP-1153 transient storage reads. -/ -theorem bridgedStraightStmt_let_tload (name : String) - (slotExpr : Compiler.Yul.YulExpr) (hSlot : BridgedExpr slotExpr) : - BridgedStraightStmt - (.let_ name (Compiler.Yul.YulExpr.call "tload" [slotExpr])) := - BridgedStraightStmt.let_ name _ (bridgedExpr_tload slotExpr hSlot) - -/-- `let name := keccak256(offsetExpr, sizeExpr)` with bridged operands is a - `BridgedStraightStmt`. Composes `BridgedStraightStmt.let_` with - `bridgedExpr_keccak256`. Matches the `let __evt_topic0 := keccak256(...)` - binding inside compiled scalar `emit` bodies. -/ -theorem bridgedStraightStmt_let_keccak256 (name : String) - (offsetExpr sizeExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : - BridgedStraightStmt - (.let_ name - (Compiler.Yul.YulExpr.call "keccak256" [offsetExpr, sizeExpr])) := - BridgedStraightStmt.let_ name _ - (bridgedExpr_keccak256 offsetExpr sizeExpr hOffset hSize) - -/-- `name := mload(offsetExpr)` analogue of `bridgedStraightStmt_let_mload` for - reassignment to an already-declared local (e.g. `retVal := mload(ptr)` - in a return-epilogue). -/ -theorem bridgedStraightStmt_assign_mload (name : String) - (offsetExpr : Compiler.Yul.YulExpr) (hOffset : BridgedExpr offsetExpr) : - BridgedStraightStmt - (.assign name (Compiler.Yul.YulExpr.call "mload" [offsetExpr])) := - BridgedStraightStmt.assign name _ (bridgedExpr_mload offsetExpr hOffset) - -/-- `name := tload(slotExpr)` analogue of `bridgedStraightStmt_let_tload`. -/ -theorem bridgedStraightStmt_assign_tload (name : String) - (slotExpr : Compiler.Yul.YulExpr) (hSlot : BridgedExpr slotExpr) : - BridgedStraightStmt - (.assign name (Compiler.Yul.YulExpr.call "tload" [slotExpr])) := - BridgedStraightStmt.assign name _ (bridgedExpr_tload slotExpr hSlot) - -/-- `name := keccak256(offsetExpr, sizeExpr)` analogue of - `bridgedStraightStmt_let_keccak256` for reassignment contexts. -/ -theorem bridgedStraightStmt_assign_keccak256 (name : String) - (offsetExpr sizeExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : - BridgedStraightStmt - (.assign name - (Compiler.Yul.YulExpr.call "keccak256" [offsetExpr, sizeExpr])) := - BridgedStraightStmt.assign name _ - (bridgedExpr_keccak256 offsetExpr sizeExpr hOffset hSize) - -/-- Convenience constructor that lifts `expr_log` through the `isYulLogName` - hypothesis for any of the five Yul log mnemonics. Callers outside this file - can produce `BridgedStraightStmt` log emissions without restating the - `isYulLogName` boolean obligation. Each emitted `logN` from the PR #1732 - proven-fragment dispatch table now has a closed bridged counterpart. -/ -theorem bridgedStraightStmt_log_of_bridged_args - (func : String) (args : List Compiler.Yul.YulExpr) - (hLog : isYulLogName func = true) - (hArgs : ∀ arg ∈ args, BridgedExpr arg) : - BridgedStraightStmt (.expr (.call func args)) := - BridgedStraightStmt.expr_log func args hLog hArgs - -/-- `BridgedStraightStmt` lifts to `BridgedStmt` via the `straight` ctor; this - is a thin convenience wrapper so that callers can chain a `logN` emission - (or any other straight-line statement) directly into a recursive body - context without retyping `BridgedStmt.straight _`. -/ -theorem bridgedStmt_of_bridgedStraightStmt {stmt : Compiler.Yul.YulStmt} - (hStmt : BridgedStraightStmt stmt) : BridgedStmt stmt := - BridgedStmt.straight stmt hStmt - -/-- Direct `BridgedStmt` version of `bridgedStraightStmt_log_of_bridged_args`: - a `logN` call (any Yul log mnemonic per `isYulLogName`) with all arguments - bridged lifts straight to `BridgedStmt`, saving the - `bridgedStmt_of_bridgedStraightStmt` wrap at the call site. -/ -theorem bridgedStmt_log_of_bridged_args - (func : String) (args : List Compiler.Yul.YulExpr) - (hLog : isYulLogName func = true) - (hArgs : ∀ arg ∈ args, BridgedExpr arg) : - BridgedStmt (.expr (.call func args)) := - bridgedStmt_of_bridgedStraightStmt - (bridgedStraightStmt_log_of_bridged_args func args hLog hArgs) - -/-- Direct `BridgedStmt` version of `bridgedStraightStmt_let_mload`: matches - the `let __evt_ptr := mload(0x40)` prologue emitted at the head of - compiled scalar `emit` bodies without requiring callers to chain an - explicit `bridgedStmt_of_bridgedStraightStmt` wrap. -/ -theorem bridgedStmt_let_mload (name : String) - (offsetExpr : Compiler.Yul.YulExpr) (hOffset : BridgedExpr offsetExpr) : - BridgedStmt (.let_ name (Compiler.Yul.YulExpr.call "mload" [offsetExpr])) := - bridgedStmt_of_bridgedStraightStmt - (bridgedStraightStmt_let_mload name offsetExpr hOffset) - -/-- Direct `BridgedStmt` version of `bridgedStraightStmt_let_tload`: the - EIP-1153 transient-load analogue of `bridgedStmt_let_mload`. -/ -theorem bridgedStmt_let_tload (name : String) - (slotExpr : Compiler.Yul.YulExpr) (hSlot : BridgedExpr slotExpr) : - BridgedStmt (.let_ name (Compiler.Yul.YulExpr.call "tload" [slotExpr])) := - bridgedStmt_of_bridgedStraightStmt - (bridgedStraightStmt_let_tload name slotExpr hSlot) - -/-- Direct `BridgedStmt` version of `bridgedStraightStmt_let_keccak256`: - matches the `let __evt_topic0 := keccak256(ptr, size)` binding between - the sig-stores and unindexed-stores blocks of compiled scalar `emit` - bodies. -/ -theorem bridgedStmt_let_keccak256 (name : String) - (offsetExpr sizeExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : - BridgedStmt - (.let_ name - (Compiler.Yul.YulExpr.call "keccak256" [offsetExpr, sizeExpr])) := - bridgedStmt_of_bridgedStraightStmt - (bridgedStraightStmt_let_keccak256 name offsetExpr sizeExpr hOffset hSize) - -/-- Direct `BridgedStmt` version of `bridgedStraightStmt_assign_mload`: - `name := mload(offsetExpr)` with a bridged offset lifts straight to - `BridgedStmt`, paralleling `bridgedStmt_let_mload` for the already-declared - variable path. -/ -theorem bridgedStmt_assign_mload (name : String) - (offsetExpr : Compiler.Yul.YulExpr) (hOffset : BridgedExpr offsetExpr) : - BridgedStmt - (.assign name (Compiler.Yul.YulExpr.call "mload" [offsetExpr])) := - bridgedStmt_of_bridgedStraightStmt - (bridgedStraightStmt_assign_mload name offsetExpr hOffset) - -/-- Direct `BridgedStmt` version of `bridgedStraightStmt_assign_tload`: - EIP-1153 transient-load analogue of `bridgedStmt_assign_mload`. -/ -theorem bridgedStmt_assign_tload (name : String) - (slotExpr : Compiler.Yul.YulExpr) (hSlot : BridgedExpr slotExpr) : - BridgedStmt - (.assign name (Compiler.Yul.YulExpr.call "tload" [slotExpr])) := - bridgedStmt_of_bridgedStraightStmt - (bridgedStraightStmt_assign_tload name slotExpr hSlot) - -/-- Direct `BridgedStmt` version of `bridgedStraightStmt_assign_keccak256`: - `name := keccak256(ptr, size)` for assigning to an already-declared - variable, paralleling `bridgedStmt_let_keccak256`. -/ -theorem bridgedStmt_assign_keccak256 (name : String) - (offsetExpr sizeExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : - BridgedStmt - (.assign name - (Compiler.Yul.YulExpr.call "keccak256" [offsetExpr, sizeExpr])) := - bridgedStmt_of_bridgedStraightStmt - (bridgedStraightStmt_assign_keccak256 name offsetExpr sizeExpr hOffset hSize) - -/-- Direct `BridgedStmt` wrapper for `mstore(offsetExpr, valExpr)` with both - expression arguments bridged. Skips the explicit `BridgedStmt.straight _` - + `BridgedStraightStmt.expr_mstore` construction at call sites for a - standalone mstore that sits in a recursive-body context (e.g. spliced - between non-straight fragments). -/ -theorem bridgedStmt_mstore_of_bridged_args - (offsetExpr valExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : - BridgedStmt - (.expr (Compiler.Yul.YulExpr.call "mstore" [offsetExpr, valExpr])) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.expr_mstore offsetExpr valExpr hOffset hVal) - -/-- Direct `BridgedStmt` wrapper for `tstore(offsetExpr, valExpr)`: EIP-1153 - transient-store analogue of `bridgedStmt_mstore_of_bridged_args`. -/ -theorem bridgedStmt_tstore_of_bridged_args - (offsetExpr valExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : - BridgedStmt - (.expr (Compiler.Yul.YulExpr.call "tstore" [offsetExpr, valExpr])) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.expr_tstore offsetExpr valExpr hOffset hVal) - -/-- Direct `BridgedStmt` wrapper for the mapping-slot storage write - `sstore(mappingSlot(baseExpr, keyExpr), valExpr)` over bridged base/key/ - value. Paralleling `bridgedStmt_mstore_of_bridged_args` for the dynamic - mapping path emitted by `compileMappingSlotWrite`. -/ -theorem bridgedStmt_sstore_mapping_of_bridged_args - (baseExpr keyExpr valExpr : Compiler.Yul.YulExpr) - (hBase : BridgedExpr baseExpr) (hKey : BridgedExpr keyExpr) - (hVal : BridgedExpr valExpr) : - BridgedStmt - (.expr (Compiler.Yul.YulExpr.call "sstore" - [Compiler.Yul.YulExpr.call "mappingSlot" [baseExpr, keyExpr], valExpr])) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.expr_sstore_mapping baseExpr keyExpr valExpr hBase hKey hVal) - -/-- Direct `BridgedStmt` wrapper for `sstore(lit slot, valExpr)` with a known - literal slot index. Matches the unpacked single-slot field write emitted - by `compileSetStorage`. -/ -theorem bridgedStmt_sstore_lit_of_bridged_val - (slot : Nat) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) : - BridgedStmt - (.expr (Compiler.Yul.YulExpr.call "sstore" - [Compiler.Yul.YulExpr.lit slot, valExpr])) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.expr_sstore_lit slot valExpr hVal) - -/-- Direct `BridgedStmt` wrapper for `sstore(ident slotName, valExpr)` where - the target slot has already been bound to a local variable (struct-member - and compatibility-write paths). -/ -theorem bridgedStmt_sstore_ident_of_bridged_val - (slotName : String) (valExpr : Compiler.Yul.YulExpr) - (hVal : BridgedExpr valExpr) : - BridgedStmt - (.expr (Compiler.Yul.YulExpr.call "sstore" - [Compiler.Yul.YulExpr.ident slotName, valExpr])) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.expr_sstore_ident slotName valExpr hVal) - -/-- Direct `BridgedStmt` wrapper for `sstore(add(leftExpr, rightExpr), valExpr)` - with bridged left/right slot-computation args and value. Covers the - storage-array element writes emitted by `compileStorageArrayPush`, - `compileStorageArrayPop`, and `compileSetStorageArrayElement`. -/ -theorem bridgedStmt_sstore_add_of_bridged_args - (leftExpr rightExpr valExpr : Compiler.Yul.YulExpr) - (hLeft : BridgedExpr leftExpr) (hRight : BridgedExpr rightExpr) - (hVal : BridgedExpr valExpr) : - BridgedStmt - (.expr (Compiler.Yul.YulExpr.call "sstore" - [Compiler.Yul.YulExpr.call "add" [leftExpr, rightExpr], valExpr])) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.expr_sstore_add leftExpr rightExpr valExpr - hLeft hRight hVal) - -/-- Direct `BridgedStmt` wrapper for the zero-arg `stop()` terminator. -/ -theorem bridgedStmt_stop : - BridgedStmt (.expr (Compiler.Yul.YulExpr.call "stop" [])) := - bridgedStmt_of_bridgedStraightStmt BridgedStraightStmt.expr_stop - -/-- Direct `BridgedStmt` wrapper for `return(offsetExpr, sizeExpr)` with both - arguments bridged. Covers the external-function non-empty-return - terminator. -/ -theorem bridgedStmt_return_of_bridged_args - (offsetExpr sizeExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : - BridgedStmt - (.expr (Compiler.Yul.YulExpr.call "return" [offsetExpr, sizeExpr])) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.expr_return offsetExpr sizeExpr hOffset hSize) - -/-- Direct `BridgedStmt` wrapper for `revert(offsetExpr, sizeExpr)`. The - underlying `BridgedStraightStmt.expr_revert` ctor takes no bridged-arg - hypotheses — revert only inspects memory range bounds via the shared - `EvmYulLean` state bridge. -/ -theorem bridgedStmt_revert - (offsetExpr sizeExpr : Compiler.Yul.YulExpr) : - BridgedStmt - (.expr (Compiler.Yul.YulExpr.call "revert" [offsetExpr, sizeExpr])) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.expr_revert offsetExpr sizeExpr) - -/-- Direct `BridgedStmt` wrapper for the zero-arg `leave` internal-function - terminator. -/ -theorem bridgedStmt_leave : BridgedStmt .leave := - bridgedStmt_of_bridgedStraightStmt BridgedStraightStmt.leave - -/-- Direct `BridgedStmt` wrapper for generic `let name := value` where - `value` is any bridged expression (not restricted to mload/tload/keccak256). - Covers the common `let tmp := ` bindings compiler-emitted - between store/read blocks. -/ -theorem bridgedStmt_let_of_bridged_val - (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) : - BridgedStmt (.let_ name value) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.let_ name value hValue) - -/-- Direct `BridgedStmt` wrapper for multi-variable `let name1, name2, ... := value`. - The underlying `BridgedStraightStmt.letMany` ctor intentionally requires no - bridged-value hypothesis — it is closed generically over the `value` - expression. -/ -theorem bridgedStmt_letMany - (names : List String) (value : Compiler.Yul.YulExpr) : - BridgedStmt (.letMany names value) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.letMany names value) - -/-- Direct `BridgedStmt` wrapper for generic `name := value` reassignment over - any bridged expression. Paralleling `bridgedStmt_let_of_bridged_val` for - the already-declared-variable path. -/ -theorem bridgedStmt_assign_of_bridged_val - (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) : - BridgedStmt (.assign name value) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.assign name value hValue) - -/-- Direct `BridgedStmt` wrapper for a standalone `comment` statement. - The underlying `BridgedStraightStmt.comment` ctor is closed generically - over the label text, so no further hypothesis is required. -/ -theorem bridgedStmt_comment (text : String) : - BridgedStmt (.comment text) := - bridgedStmt_of_bridgedStraightStmt (BridgedStraightStmt.comment text) - -/-- Direct `BridgedStmt` wrapper for a Yul `function` declaration at the - straight-line level. Mirrors `BridgedStraightStmt.funcDef`, which is - closed generically over the function name, params/rets, and body — - callers needing body-level bridgedness must use a separate body - closure predicate. -/ -theorem bridgedStmt_funcDef - (name : String) (params rets : List String) - (body : List Compiler.Yul.YulStmt) : - BridgedStmt (.funcDef name params rets body) := - bridgedStmt_of_bridgedStraightStmt - (BridgedStraightStmt.funcDef name params rets body) - -/-- List-level lift: any list satisfying `BridgedStraightStmts` also satisfies - the recursive `BridgedStmts` predicate, since `BridgedStraightStmt` lifts - pointwise via `bridgedStmt_of_bridgedStraightStmt`. Useful when a compiler - fragment emits a pure-straight segment (e.g. the `sigStores` / - `unindexedStores` lists inside scalar `emit` bodies) that needs to slot - into a recursive-statement body context. -/ -theorem BridgedStmts_of_BridgedStraightStmts - {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStraightStmts stmts) : - BridgedStmts stmts := by - intro stmt hMem - exact bridgedStmt_of_bridgedStraightStmt (hStmts stmt hMem) - -/-- Cons a `BridgedStraightStmt` head onto a `BridgedStmts` tail without - retyping `bridgedStmt_of_bridgedStraightStmt` at the call site. Shortens - scalar-emit body assembly, where each straight-line prologue/terminator - statement (`let __evt_ptr := mload ...`, `let __evt_topic0 := keccak256 ...`, - final `logN(...)`) is naturally a `BridgedStraightStmt` being attached to - a `BridgedStmts`-typed recursive tail. -/ -theorem BridgedStmts_cons_straight {stmt : Compiler.Yul.YulStmt} - {stmts : List Compiler.Yul.YulStmt} - (hStmt : BridgedStraightStmt stmt) (hStmts : BridgedStmts stmts) : - BridgedStmts (stmt :: stmts) := - BridgedStmts_cons (bridgedStmt_of_bridgedStraightStmt hStmt) hStmts - -/-- Singleton counterpart to `BridgedStmts_cons_straight`: a single - `BridgedStraightStmt` lifts to the one-element `BridgedStmts [stmt]` list. - Saves a nested `bridgedStmt_of_bridgedStraightStmt` when the whole body is - just one straight-line statement (e.g. a terminator-only fragment). -/ -theorem BridgedStmts_singleton_straight {stmt : Compiler.Yul.YulStmt} - (hStmt : BridgedStraightStmt stmt) : BridgedStmts [stmt] := - BridgedStmts_singleton (bridgedStmt_of_bridgedStraightStmt hStmt) - -/-- Append counterpart to `BridgedStmts_cons_straight` / `_singleton_straight`: - prepend a `BridgedStraightStmts`-typed segment to a `BridgedStmts`-typed - tail. Supports scalar-emit body assembly where the prologue and store - blocks are naturally `BridgedStraightStmts` (map-shaped or cons-built) - that need to sit in front of a `BridgedStmts` recursive-body continuation - without retyping the list-level lift at the call site. -/ -theorem BridgedStmts_append_straight {xs ys : List Compiler.Yul.YulStmt} - (hXs : BridgedStraightStmts xs) (hYs : BridgedStmts ys) : - BridgedStmts (xs ++ ys) := - BridgedStmts_append (BridgedStmts_of_BridgedStraightStmts hXs) hYs - -/-- `BridgedStmts` analogue of `BridgedStraightStmts_map_mstore`: a list of - `(offset, value)` expression pairs with both components bridged maps to - a `BridgedStmts` list of `mstore(offset, value)` statements. Directly - supports scalar `emit` bodies where `sigStores` / `unindexedStores` are - built as `List YulStmt` via `.map` over pair-shaped data and must slot - into a recursive-body context. -/ -theorem BridgedStmts_map_mstore - (pairs : List (Compiler.Yul.YulExpr × Compiler.Yul.YulExpr)) - (hPairs : ∀ p ∈ pairs, BridgedExpr p.1 ∧ BridgedExpr p.2) : - BridgedStmts - (pairs.map fun p => - Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "mstore" [p.1, p.2])) := - BridgedStmts_of_BridgedStraightStmts (BridgedStraightStmts_map_mstore pairs hPairs) - -/-- Wrap a `BridgedStmts`-typed list under `BridgedStmt.block`. The ctor's - pointwise `∀ stmt ∈ stmts, BridgedStmt stmt` obligation is definitionally - equal to `BridgedStmts stmts`, so this is a one-line convenience. Directly - supports the scalar `emit` body shape, which compiles to a single outer - `[YulStmt.block body]` wrapping all bridged fragments. -/ -theorem bridgedStmt_block_of_bridgedStmts - {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : - BridgedStmt (.block stmts) := - BridgedStmt.block stmts hStmts - -/-- `BridgedStmts` analogue of a single-element list wrapping a `.block` node. - Convenient for compiler-emitted shapes that put an entire function body - inside a single top-level block (e.g. scalar `emit`, runtime dispatch). -/ -theorem BridgedStmts_singleton_block - {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStmts stmts) : - BridgedStmts [Compiler.Yul.YulStmt.block stmts] := - BridgedStmts_singleton (bridgedStmt_block_of_bridgedStmts hStmts) - -/-- Cons a `.block` node to an already-bridged `BridgedStmts` tail. Useful when - a compiled list interleaves a scoped block fragment with surrounding - straight-line or other bridged statements. -/ -theorem BridgedStmts_cons_block - {stmts : List Compiler.Yul.YulStmt} {rest : List Compiler.Yul.YulStmt} - (hStmts : BridgedStmts stmts) (hRest : BridgedStmts rest) : - BridgedStmts (Compiler.Yul.YulStmt.block stmts :: rest) := - BridgedStmts_cons (bridgedStmt_block_of_bridgedStmts hStmts) hRest - -/-- Wrap a bridged condition plus `BridgedStmts`-typed body under - `BridgedStmt.if_`. Parallels `bridgedStmt_block_of_bridgedStmts` for - the single-branch conditional shape (no else) emitted by require/revert - guards and similar fragments. -/ -theorem bridgedStmt_if_of_bridgedStmts - {cond : Compiler.Yul.YulExpr} {body : List Compiler.Yul.YulStmt} - (hCond : BridgedExpr cond) (hBody : BridgedStmts body) : - BridgedStmt (.if_ cond body) := - BridgedStmt.if_ cond body hCond hBody - -/-- `BridgedStmts` singleton wrapping a Yul `if cond { body }` node. Useful when - a compiled body reduces to a lone guard fragment (e.g. the callvalue or - calldatasize guards emitted at the top of a dispatch block). -/ -theorem BridgedStmts_singleton_if - {cond : Compiler.Yul.YulExpr} {body : List Compiler.Yul.YulStmt} - (hCond : BridgedExpr cond) (hBody : BridgedStmts body) : - BridgedStmts [Compiler.Yul.YulStmt.if_ cond body] := - BridgedStmts_singleton (bridgedStmt_if_of_bridgedStmts hCond hBody) - -/-- Cons a Yul `if cond { body }` node onto an already-bridged `BridgedStmts` - tail. Typical shape: a guard statement followed by the rest of a compiled - body list. -/ -theorem BridgedStmts_cons_if - {cond : Compiler.Yul.YulExpr} {body : List Compiler.Yul.YulStmt} - {rest : List Compiler.Yul.YulStmt} - (hCond : BridgedExpr cond) (hBody : BridgedStmts body) - (hRest : BridgedStmts rest) : - BridgedStmts (Compiler.Yul.YulStmt.if_ cond body :: rest) := - BridgedStmts_cons (bridgedStmt_if_of_bridgedStmts hCond hBody) hRest - -/-- Wrap four bridged components (init/post/body `BridgedStmts`, cond - `BridgedExpr`) under `BridgedStmt.for_`. Parallels the block/if wrappers - for the Yul `for { init } cond { post } { body }` shape emitted by - compiler loops. Each list hypothesis is definitionally the pointwise - `∀ stmt ∈ _, BridgedStmt stmt` the ctor expects. -/ -theorem bridgedStmt_for_of_bridgedStmts - {init : List Compiler.Yul.YulStmt} {cond : Compiler.Yul.YulExpr} - {post body : List Compiler.Yul.YulStmt} - (hInit : BridgedStmts init) (hCond : BridgedExpr cond) - (hPost : BridgedStmts post) (hBody : BridgedStmts body) : - BridgedStmt (.for_ init cond post body) := - BridgedStmt.for_ init cond post body hInit hCond hPost hBody - -/-- `BridgedStmts` singleton wrapping a single Yul `for` loop node. Useful - when a compiled body reduces to a lone loop. -/ -theorem BridgedStmts_singleton_for - {init : List Compiler.Yul.YulStmt} {cond : Compiler.Yul.YulExpr} - {post body : List Compiler.Yul.YulStmt} - (hInit : BridgedStmts init) (hCond : BridgedExpr cond) - (hPost : BridgedStmts post) (hBody : BridgedStmts body) : - BridgedStmts [Compiler.Yul.YulStmt.for_ init cond post body] := - BridgedStmts_singleton - (bridgedStmt_for_of_bridgedStmts hInit hCond hPost hBody) - -/-- Cons a Yul `for` loop node onto an already-bridged `BridgedStmts` tail. - Typical shape: a loop followed by additional straight-line or bridged - statements in a compiled body list. -/ -theorem BridgedStmts_cons_for - {init : List Compiler.Yul.YulStmt} {cond : Compiler.Yul.YulExpr} - {post body : List Compiler.Yul.YulStmt} - {rest : List Compiler.Yul.YulStmt} - (hInit : BridgedStmts init) (hCond : BridgedExpr cond) - (hPost : BridgedStmts post) (hBody : BridgedStmts body) - (hRest : BridgedStmts rest) : - BridgedStmts (Compiler.Yul.YulStmt.for_ init cond post body :: rest) := - BridgedStmts_cons - (bridgedStmt_for_of_bridgedStmts hInit hCond hPost hBody) hRest - -/-- Wrap a bridged scrutinee expression together with per-case and default - body hypotheses under `BridgedStmt.switch`. Parallels the block/if/for - wrappers for the Yul `switch` dispatch shape emitted by the compiler's - selector/function dispatcher. Each body-side hypothesis is precisely the - pointwise `∀ stmt ∈ _, BridgedStmt stmt` that the ctor expects. -/ -theorem bridgedStmt_switch_of_bridgedStmts - {expr : Compiler.Yul.YulExpr} - {cases : List (Nat × List Compiler.Yul.YulStmt)} - {defaultCase : Option (List Compiler.Yul.YulStmt)} - (hExpr : BridgedExpr expr) - (hCases : ∀ scrutinee value body, - cases.find? (fun x => decide (x.fst = scrutinee)) = some (value, body) → - ∀ stmt ∈ body, BridgedStmt stmt) - (hDefault : ∀ body, defaultCase = some body → - ∀ stmt ∈ body, BridgedStmt stmt) : - BridgedStmt (.switch expr cases defaultCase) := - BridgedStmt.switch expr cases defaultCase hExpr hCases hDefault - -/-- `BridgedStmts` singleton wrapping a single Yul `switch` node. Completes - block/if/for/switch parity for list composers. -/ -theorem BridgedStmts_singleton_switch - {expr : Compiler.Yul.YulExpr} - {cases : List (Nat × List Compiler.Yul.YulStmt)} - {defaultCase : Option (List Compiler.Yul.YulStmt)} - (hExpr : BridgedExpr expr) - (hCases : ∀ scrutinee value body, - cases.find? (fun x => decide (x.fst = scrutinee)) = some (value, body) → - ∀ stmt ∈ body, BridgedStmt stmt) - (hDefault : ∀ body, defaultCase = some body → - ∀ stmt ∈ body, BridgedStmt stmt) : - BridgedStmts [Compiler.Yul.YulStmt.switch expr cases defaultCase] := - BridgedStmts_singleton - (bridgedStmt_switch_of_bridgedStmts hExpr hCases hDefault) - -/-- Cons a Yul `switch` node onto an already-bridged `BridgedStmts` tail. - Typical shape: selector/function dispatch followed by a trailing - fallback fragment in a compiled body list. -/ -theorem BridgedStmts_cons_switch - {expr : Compiler.Yul.YulExpr} - {cases : List (Nat × List Compiler.Yul.YulStmt)} - {defaultCase : Option (List Compiler.Yul.YulStmt)} - {rest : List Compiler.Yul.YulStmt} - (hExpr : BridgedExpr expr) - (hCases : ∀ scrutinee value body, - cases.find? (fun x => decide (x.fst = scrutinee)) = some (value, body) → - ∀ stmt ∈ body, BridgedStmt stmt) - (hDefault : ∀ body, defaultCase = some body → - ∀ stmt ∈ body, BridgedStmt stmt) - (hRest : BridgedStmts rest) : - BridgedStmts - (Compiler.Yul.YulStmt.switch expr cases defaultCase :: rest) := - BridgedStmts_cons - (bridgedStmt_switch_of_bridgedStmts hExpr hCases hDefault) hRest - -/-- Convenience wrapper: when the block body is entirely straight-line, - callers can supply a `BridgedStraightStmts` hypothesis directly without - manually lifting through `BridgedStmts_of_BridgedStraightStmts`. -/ -theorem bridgedStmt_block_of_bridgedStraightStmts - {stmts : List Compiler.Yul.YulStmt} (hStmts : BridgedStraightStmts stmts) : - BridgedStmt (.block stmts) := - bridgedStmt_block_of_bridgedStmts (BridgedStmts_of_BridgedStraightStmts hStmts) - -/-- Convenience wrapper: single-branch `if` whose body is entirely - straight-line. Mirrors `bridgedStmt_block_of_bridgedStraightStmts` for - the guard-only conditional shape. -/ -theorem bridgedStmt_if_of_bridgedStraightStmts - {cond : Compiler.Yul.YulExpr} {body : List Compiler.Yul.YulStmt} - (hCond : BridgedExpr cond) (hBody : BridgedStraightStmts body) : - BridgedStmt (.if_ cond body) := - bridgedStmt_if_of_bridgedStmts hCond (BridgedStmts_of_BridgedStraightStmts hBody) - -/-- Convenience wrapper: `for { init } cond { post } { body }` whose four - list-typed components are each entirely straight-line. Mirrors the block - and if variants above for the loop shape. -/ -theorem bridgedStmt_for_of_bridgedStraightStmts - {init : List Compiler.Yul.YulStmt} {cond : Compiler.Yul.YulExpr} - {post body : List Compiler.Yul.YulStmt} - (hInit : BridgedStraightStmts init) (hCond : BridgedExpr cond) - (hPost : BridgedStraightStmts post) (hBody : BridgedStraightStmts body) : - BridgedStmt (.for_ init cond post body) := - bridgedStmt_for_of_bridgedStmts - (BridgedStmts_of_BridgedStraightStmts hInit) - hCond - (BridgedStmts_of_BridgedStraightStmts hPost) - (BridgedStmts_of_BridgedStraightStmts hBody) - -/-- `BridgedStmts` analogue of `BridgedStraightStmts_map_tstore`, for the - transient-store variant of the map helper above. -/ -theorem BridgedStmts_map_tstore - (pairs : List (Compiler.Yul.YulExpr × Compiler.Yul.YulExpr)) - (hPairs : ∀ p ∈ pairs, BridgedExpr p.1 ∧ BridgedExpr p.2) : - BridgedStmts - (pairs.map fun p => - Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "tstore" [p.1, p.2])) := - BridgedStmts_of_BridgedStraightStmts (BridgedStraightStmts_map_tstore pairs hPairs) - -/-- The common `revert(0, 0)` failure terminator as a `BridgedStmt`. Used by - compiler-emitted guards (callvalue, calldatasize, require) whose failure - branch is a single unconditional revert with zero offset/size. Exposed - publicly so downstream body-closure proofs can reuse it. -/ -theorem bridgedStmt_revert_zero : - BridgedStmt - (Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "revert" - [Compiler.Yul.YulExpr.lit 0, Compiler.Yul.YulExpr.lit 0])) := - BridgedStmt.straight _ - (BridgedStraightStmt.expr_revert - (Compiler.Yul.YulExpr.lit 0) (Compiler.Yul.YulExpr.lit 0)) - -/-- `BridgedStmts` singleton wrapping a single `revert(0, 0)`. Matches the - canonical guard-body shape `[YulStmt.expr (call "revert" [lit 0, lit 0])]` - emitted by callvalue/calldatasize/require guards. -/ -theorem BridgedStmts_singleton_revert_zero : - BridgedStmts - [Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "revert" - [Compiler.Yul.YulExpr.lit 0, Compiler.Yul.YulExpr.lit 0])] := - BridgedStmts_singleton bridgedStmt_revert_zero - -/-- `BridgedStmts` singleton wrapping a single `.comment text` node. Useful - when a compiled body reduces to a lone comment label (rare, but present - as a terminal marker in some codegen paths). -/ -theorem BridgedStmts_singleton_comment (text : String) : - BridgedStmts [Compiler.Yul.YulStmt.comment text] := - BridgedStmts_singleton (bridgedStmt_comment text) - -/-- Cons a `.comment text` node onto an already-bridged `BridgedStmts` tail. - Matches the canonical shape emitted by the dispatcher and most function - bodies, where a single label-prefix comment sits at the head of the - compiled statement list. -/ -theorem BridgedStmts_cons_comment - (text : String) {rest : List Compiler.Yul.YulStmt} - (hRest : BridgedStmts rest) : - BridgedStmts (Compiler.Yul.YulStmt.comment text :: rest) := - BridgedStmts_cons (bridgedStmt_comment text) hRest - -/-- `BridgedStmts` singleton wrapping a single `.let_ name value` node over a - bridged value expression. Mirrors the bridged-value `let` shape emitted - throughout the dispatcher and runtime-common prologues. -/ -theorem BridgedStmts_singleton_let - (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) : - BridgedStmts [Compiler.Yul.YulStmt.let_ name value] := - BridgedStmts_singleton (bridgedStmt_let_of_bridged_val name value hValue) - -/-- Cons a `.let_ name value` node over a bridged value expression onto an - already-bridged `BridgedStmts` tail. Covers the common prologue shape - where a pure `let tmp := ` binding precedes subsequent - bridged statements. -/ -theorem BridgedStmts_cons_let - (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts (Compiler.Yul.YulStmt.let_ name value :: rest) := - BridgedStmts_cons (bridgedStmt_let_of_bridged_val name value hValue) hRest - -/-- `BridgedStmts` singleton wrapping a single `.assign name value` node over - a bridged value expression. Mirrors `BridgedStmts_singleton_let` for the - already-declared-variable path. -/ -theorem BridgedStmts_singleton_assign - (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) : - BridgedStmts [Compiler.Yul.YulStmt.assign name value] := - BridgedStmts_singleton (bridgedStmt_assign_of_bridged_val name value hValue) - -/-- Cons a `.assign name value` node over a bridged value expression onto an - already-bridged `BridgedStmts` tail. Mirrors `BridgedStmts_cons_let` for - the already-declared-variable path, covering `x := ` - compiler-emitted reassignments between bridged statements. -/ -theorem BridgedStmts_cons_assign - (name : String) (value : Compiler.Yul.YulExpr) (hValue : BridgedExpr value) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts (Compiler.Yul.YulStmt.assign name value :: rest) := - BridgedStmts_cons (bridgedStmt_assign_of_bridged_val name value hValue) hRest - -/-- `BridgedStmts` singleton wrapping a single `.letMany names value` node. - The underlying `BridgedStraightStmt.letMany` ctor is closed generically - over `value`, so no bridged-value hypothesis is needed. Mirrors the - let/assign singletons for the multi-binding destructuring path. -/ -theorem BridgedStmts_singleton_letMany - (names : List String) (value : Compiler.Yul.YulExpr) : - BridgedStmts [Compiler.Yul.YulStmt.letMany names value] := - BridgedStmts_singleton (bridgedStmt_letMany names value) - -/-- Cons a `.letMany names value` node onto an already-bridged `BridgedStmts` - tail. Matches compiler shapes that introduce multiple bindings from a - single right-hand side (e.g. multi-return intrinsics). -/ -theorem BridgedStmts_cons_letMany - (names : List String) (value : Compiler.Yul.YulExpr) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts (Compiler.Yul.YulStmt.letMany names value :: rest) := - BridgedStmts_cons (bridgedStmt_letMany names value) hRest - -/-- `BridgedStmts` singleton wrapping the zero-arg `stop()` terminator. Common - terminal shape for external-function bodies that return no data. -/ -theorem BridgedStmts_singleton_stop : - BridgedStmts [Compiler.Yul.YulStmt.expr (Compiler.Yul.YulExpr.call "stop" [])] := - BridgedStmts_singleton bridgedStmt_stop - -/-- Cons the zero-arg `stop()` terminator node onto an already-bridged - `BridgedStmts` tail. Mirrors `BridgedStmts_cons_leave` for the - external-function terminator path. -/ -theorem BridgedStmts_cons_stop - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts (Compiler.Yul.YulStmt.expr (Compiler.Yul.YulExpr.call "stop" []) :: rest) := - BridgedStmts_cons bridgedStmt_stop hRest - -/-- `BridgedStmts` singleton wrapping the zero-arg `leave` internal-function - terminator. Common terminal shape for compiled internal-function bodies. -/ -theorem BridgedStmts_singleton_leave : - BridgedStmts [Compiler.Yul.YulStmt.leave] := - BridgedStmts_singleton bridgedStmt_leave - -/-- Cons a `.leave` terminator node onto an already-bridged `BridgedStmts` - tail. Useful when an internal-return shape is followed by dead-code - cleanup in compiled output. -/ -theorem BridgedStmts_cons_leave - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts (Compiler.Yul.YulStmt.leave :: rest) := - BridgedStmts_cons bridgedStmt_leave hRest - -/-- `BridgedStmts` singleton wrapping a `return(offset, size)` terminator with - both args bridged. Common terminal shape for external-function bodies - that return non-empty data. -/ -theorem BridgedStmts_singleton_return - (offsetExpr sizeExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) : - BridgedStmts - [Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "return" [offsetExpr, sizeExpr])] := - BridgedStmts_singleton - (bridgedStmt_return_of_bridged_args offsetExpr sizeExpr hOffset hSize) - -/-- Cons a `return(offset, size)` terminator node onto an already-bridged - `BridgedStmts` tail. Mirrors `BridgedStmts_cons_stop` for the non-empty - return path. -/ -theorem BridgedStmts_cons_return - (offsetExpr sizeExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hSize : BridgedExpr sizeExpr) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts - (Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "return" [offsetExpr, sizeExpr]) :: rest) := - BridgedStmts_cons - (bridgedStmt_return_of_bridged_args offsetExpr sizeExpr hOffset hSize) hRest - -/-- `BridgedStmts` singleton wrapping a `revert(offset, size)` terminator. - The underlying `BridgedStraightStmt.expr_revert` ctor takes no - bridged-arg hypotheses; revert only inspects memory range bounds via - the shared `EvmYulLean` state bridge. -/ -theorem BridgedStmts_singleton_revert - (offsetExpr sizeExpr : Compiler.Yul.YulExpr) : - BridgedStmts - [Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "revert" [offsetExpr, sizeExpr])] := - BridgedStmts_singleton (bridgedStmt_revert offsetExpr sizeExpr) - -/-- Cons a `revert(offset, size)` terminator node onto an already-bridged - `BridgedStmts` tail. Generalizes `BridgedStmts_singleton_revert_zero` - to arbitrary offset/size expressions. -/ -theorem BridgedStmts_cons_revert - (offsetExpr sizeExpr : Compiler.Yul.YulExpr) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts - (Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "revert" [offsetExpr, sizeExpr]) :: rest) := - BridgedStmts_cons (bridgedStmt_revert offsetExpr sizeExpr) hRest - -/-- `BridgedStmts` singleton wrapping a single `mstore(offset, val)` node over - bridged offset/value expressions. Common scratchpad-write shape in - scalar-emit prologues. -/ -theorem BridgedStmts_singleton_mstore - (offsetExpr valExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : - BridgedStmts - [Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "mstore" [offsetExpr, valExpr])] := - BridgedStmts_singleton (bridgedStmt_mstore_of_bridged_args offsetExpr valExpr hOffset hVal) - -/-- Cons an `mstore(offset, val)` node over bridged offset/value expressions - onto an already-bridged `BridgedStmts` tail. Matches the scratchpad-write - shape that precedes subsequent bridged statements in emit/keccak paths. -/ -theorem BridgedStmts_cons_mstore - (offsetExpr valExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts - (Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "mstore" [offsetExpr, valExpr]) :: rest) := - BridgedStmts_cons (bridgedStmt_mstore_of_bridged_args offsetExpr valExpr hOffset hVal) hRest - -/-- `BridgedStmts` singleton wrapping a single `tstore(offset, val)` node over - bridged offset/value expressions. Transient-storage analogue of - `BridgedStmts_singleton_mstore` for reentrancy-guard / scratch paths. -/ -theorem BridgedStmts_singleton_tstore - (offsetExpr valExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) : - BridgedStmts - [Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "tstore" [offsetExpr, valExpr])] := - BridgedStmts_singleton (bridgedStmt_tstore_of_bridged_args offsetExpr valExpr hOffset hVal) - -/-- Cons a `tstore(offset, val)` node over bridged offset/value expressions onto - an already-bridged `BridgedStmts` tail. Transient-storage analogue of - `BridgedStmts_cons_mstore` for reentrancy-guard / scratch paths. -/ -theorem BridgedStmts_cons_tstore - (offsetExpr valExpr : Compiler.Yul.YulExpr) - (hOffset : BridgedExpr offsetExpr) (hVal : BridgedExpr valExpr) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts - (Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "tstore" [offsetExpr, valExpr]) :: rest) := - BridgedStmts_cons (bridgedStmt_tstore_of_bridged_args offsetExpr valExpr hOffset hVal) hRest - -/-- `BridgedStmts` singleton wrapping a single `sstore(lit slot, val)` node - over a bridged value expression. Matches the unpacked single-slot field - write emitted by `compileSetStorage`. -/ -theorem BridgedStmts_singleton_sstore_lit - (slot : Nat) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) : - BridgedStmts - [Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "sstore" - [Compiler.Yul.YulExpr.lit slot, valExpr])] := - BridgedStmts_singleton (bridgedStmt_sstore_lit_of_bridged_val slot valExpr hVal) - -/-- Cons a `sstore(lit slot, val)` node over a bridged value expression onto - an already-bridged `BridgedStmts` tail. Covers the common packed-storage - layout where sequential literal-slot writes precede subsequent bridged - statements. -/ -theorem BridgedStmts_cons_sstore_lit - (slot : Nat) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts - (Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "sstore" - [Compiler.Yul.YulExpr.lit slot, valExpr]) :: rest) := - BridgedStmts_cons (bridgedStmt_sstore_lit_of_bridged_val slot valExpr hVal) hRest - -/-- `BridgedStmts` singleton wrapping a single `sstore(ident slotName, val)` - node over a bridged value expression. Matches dynamic-slot single writes - where the slot identifier has been resolved to a local `let` binding - (e.g. from `mappingSlot(baseSlot, key)`). -/ -theorem BridgedStmts_singleton_sstore_ident - (slotName : String) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) : - BridgedStmts - [Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "sstore" - [Compiler.Yul.YulExpr.ident slotName, valExpr])] := - BridgedStmts_singleton (bridgedStmt_sstore_ident_of_bridged_val slotName valExpr hVal) - -/-- Cons a `sstore(ident slotName, val)` node over a bridged value expression - onto an already-bridged `BridgedStmts` tail. Covers mapping-write shapes - where a resolved slot identifier drives sequential bridged writes. -/ -theorem BridgedStmts_cons_sstore_ident - (slotName : String) (valExpr : Compiler.Yul.YulExpr) (hVal : BridgedExpr valExpr) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts - (Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "sstore" - [Compiler.Yul.YulExpr.ident slotName, valExpr]) :: rest) := - BridgedStmts_cons (bridgedStmt_sstore_ident_of_bridged_val slotName valExpr hVal) hRest - -/-- `BridgedStmts` singleton wrapping `sstore(mappingSlot(base, key), val)` over - bridged argument expressions. Mirrors the mstore/tstore/sstore_lit/sstore_ident - singletons for the mapping-write path emitted by `setMapping`/`setMappingUint`. -/ -theorem BridgedStmts_singleton_sstore_mapping - (baseExpr keyExpr valExpr : Compiler.Yul.YulExpr) - (hBase : BridgedExpr baseExpr) (hKey : BridgedExpr keyExpr) - (hVal : BridgedExpr valExpr) : - BridgedStmts - [Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "sstore" - [Compiler.Yul.YulExpr.call "mappingSlot" [baseExpr, keyExpr], valExpr])] := - BridgedStmts_singleton - (bridgedStmt_sstore_mapping_of_bridged_args baseExpr keyExpr valExpr hBase hKey hVal) - -/-- Cons an `sstore(mappingSlot(base, key), val)` node over bridged argument - expressions onto an already-bridged `BridgedStmts` tail. Covers the common - mapping-write shape where a single mapping write precedes subsequent - bridged statements. -/ -theorem BridgedStmts_cons_sstore_mapping - (baseExpr keyExpr valExpr : Compiler.Yul.YulExpr) - (hBase : BridgedExpr baseExpr) (hKey : BridgedExpr keyExpr) - (hVal : BridgedExpr valExpr) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts - (Compiler.Yul.YulStmt.expr - (Compiler.Yul.YulExpr.call "sstore" - [Compiler.Yul.YulExpr.call "mappingSlot" [baseExpr, keyExpr], valExpr]) :: rest) := - BridgedStmts_cons - (bridgedStmt_sstore_mapping_of_bridged_args baseExpr keyExpr valExpr hBase hKey hVal) - hRest - -/-- `BridgedStmts` singleton wrapping a single `logN(args...)` event-emission - call over bridged argument expressions. Mirrors the mstore/tstore/sstore - singletons for the EVM log emission path (log0/log1/log2/log3/log4). -/ -theorem BridgedStmts_singleton_log - (func : String) (args : List Compiler.Yul.YulExpr) - (hLog : isYulLogName func = true) - (hArgs : ∀ arg ∈ args, BridgedExpr arg) : - BridgedStmts [Compiler.Yul.YulStmt.expr (Compiler.Yul.YulExpr.call func args)] := - BridgedStmts_singleton (bridgedStmt_log_of_bridged_args func args hLog hArgs) - -/-- Cons a `logN(args...)` event-emission call over bridged argument - expressions onto an already-bridged `BridgedStmts` tail. Covers the - common event-emission shape where a topic+data encoding block ends - with the log call before subsequent bridged statements. -/ -theorem BridgedStmts_cons_log - (func : String) (args : List Compiler.Yul.YulExpr) - (hLog : isYulLogName func = true) - (hArgs : ∀ arg ∈ args, BridgedExpr arg) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts - (Compiler.Yul.YulStmt.expr (Compiler.Yul.YulExpr.call func args) :: rest) := - BridgedStmts_cons (bridgedStmt_log_of_bridged_args func args hLog hArgs) hRest - -/-- `BridgedStmts` singleton wrapping a single `.funcDef name params rets body` - node. The underlying `BridgedStraightStmt.funcDef` ctor is closed - generically over the body, so no body-level bridgedness hypothesis is - needed here — callers needing body-level equivalence must layer a - separate body-closure predicate. Mirrors the comment/let/assign/letMany - singletons for the function-declaration path. -/ -theorem BridgedStmts_singleton_funcDef - (name : String) (params rets : List String) (body : List Compiler.Yul.YulStmt) : - BridgedStmts [Compiler.Yul.YulStmt.funcDef name params rets body] := - BridgedStmts_singleton (bridgedStmt_funcDef name params rets body) - -/-- Cons a `.funcDef name params rets body` node onto an already-bridged - `BridgedStmts` tail. Matches compiler shapes that declare helper - functions (e.g. `mappingSlot`) ahead of the runtime statement list. -/ -theorem BridgedStmts_cons_funcDef - (name : String) (params rets : List String) (body : List Compiler.Yul.YulStmt) - {rest : List Compiler.Yul.YulStmt} (hRest : BridgedStmts rest) : - BridgedStmts (Compiler.Yul.YulStmt.funcDef name params rets body :: rest) := - BridgedStmts_cons (bridgedStmt_funcDef name params rets body) hRest - -theorem callvalueGuard_bridged : BridgedStmt Compiler.CodegenCommon.callvalueGuard := by + +private theorem callvalueGuard_bridged : BridgedStmt Compiler.CodegenCommon.callvalueGuard := by unfold Compiler.CodegenCommon.callvalueGuard exact bridgedStmt_if_of_bridgedStmts bridgedExpr_callvalue BridgedStmts_singleton_revert_zero -theorem calldatasizeGuard_bridged (numParams : Nat) : +private theorem calldatasizeGuard_bridged (numParams : Nat) : BridgedStmt (Compiler.CodegenCommon.calldatasizeGuard numParams) := by unfold Compiler.CodegenCommon.calldatasizeGuard exact bridgedStmt_if_of_bridgedStmts (bridgedExpr_calldatasize_lt (4 + numParams * 32)) BridgedStmts_singleton_revert_zero +/-- Dispatch guards preserve bridgedness around an already-bridged entrypoint +body. -/ theorem dispatchBody_bridged (payable : Bool) (label : String) (body : List Compiler.Yul.YulStmt) (hBody : BridgedStmts body) : BridgedStmts (Compiler.CodegenCommon.dispatchBody payable label body) := by @@ -2381,6 +1229,8 @@ theorem dispatchBody_bridged (payable : Bool) (label : String) (BridgedStmts_cons callvalueGuard_bridged hBody) · exact BridgedStmts_cons_comment label hBody +/-- The generated default dispatch case is bridged whenever its optional +fallback and receive bodies are bridged. -/ theorem defaultDispatchCase_bridged (fallback receive : Option Compiler.IREntrypoint) (hFallback : ∀ fb, fallback = some fb → BridgedStmts fb.body) @@ -2422,7 +1272,9 @@ theorem defaultDispatchCase_bridged (hFallback fb rfl)) BridgedStmts_nil)) -private theorem switchCases_bridged +/-- Every lowered generated selector-switch case is bridged when every source +function body in the case list is bridged. -/ +theorem switchCases_bridged (funcs : List Compiler.IRFunction) (hFunctions : ∀ fn, fn ∈ funcs → BridgedStmts fn.body) : ∀ scrutinee value body, @@ -2446,6 +1298,8 @@ private theorem switchCases_bridged (BridgedStmts_cons (calldatasizeGuard_bridged fn.params.length) (hFunctions fn hFn)) +/-- The generated runtime selector switch is bridged from bridged external +function, fallback, and receive bodies. -/ theorem buildSwitch_bridged (funcs : List Compiler.IRFunction) (fallback receive : Option Compiler.IREntrypoint) @@ -2469,11 +1323,15 @@ theorem buildSwitch_bridged exact defaultDispatchCase_bridged fallback receive hFallback hReceive)) BridgedStmts_nil))) +/-- The generated `mappingSlot` helper body is in the bridged fragment. -/ theorem mappingSlotFuncAt_bridged (scratchBase : Nat) : BridgedStmt (Compiler.CodegenCommon.mappingSlotFuncAt scratchBase) := by unfold Compiler.CodegenCommon.mappingSlotFuncAt exact bridgedStmt_funcDef "mappingSlot" ["baseSlot", "key"] ["slot"] _ +/-- Generic bridge proof for all generated runtime code emitted from an +`IRContract`: mapping helper, internal helpers, dispatcher switch, and optional +fallback/receive bodies. -/ theorem runtimeCode_bridged (contract : Compiler.IRContract) (hFunctions : ∀ fn, fn ∈ contract.functions → BridgedStmts fn.body) @@ -2492,6 +1350,8 @@ theorem runtimeCode_bridged (buildSwitch_bridged contract.functions contract.fallbackEntrypoint contract.receiveEntrypoint hFunctions hFallback hReceive)) +/-- The runtime code emitted by `emitYul` is a bridged execution target whenever +all constituent function, helper, fallback, and receive bodies are bridged. -/ theorem emitYul_runtimeCode_bridged (contract : Compiler.IRContract) (hFunctions : ∀ fn, fn ∈ contract.functions → BridgedStmts fn.body) @@ -2503,7 +1363,7 @@ theorem emitYul_runtimeCode_bridged simpa [Compiler.emitYul] using runtimeCode_bridged contract hFunctions hFallback hReceive hInternals) -theorem execYulFuelWithBackend_eq_on_bridged_target +private theorem execYulFuelWithBackend_eq_on_bridged_target (fuel : Nat) (state : YulState) (target : YulExecTarget) (hTarget : BridgedTarget target) : execYulFuelWithBackend .verity fuel state target = @@ -2616,7 +1476,7 @@ theorem execYulFuelWithBackend_eq_on_bridged_target | «stop» _ => rfl | «revert» _ => rfl -theorem execYulFuelWithBackend_eq_on_bridged_stmt +private theorem execYulFuelWithBackend_eq_on_bridged_stmt (fuel : Nat) (state : YulState) (stmt : Compiler.Yul.YulStmt) (hStmt : BridgedStmt stmt) : execYulFuelWithBackend .verity fuel state (.stmt stmt) = @@ -2624,7 +1484,7 @@ theorem execYulFuelWithBackend_eq_on_bridged_stmt execYulFuelWithBackend_eq_on_bridged_target fuel state (.stmt stmt) (.stmt stmt hStmt) -theorem execYulFuelWithBackend_eq_on_bridged_stmts +private theorem execYulFuelWithBackend_eq_on_bridged_stmts (fuel : Nat) (state : YulState) (stmts : List Compiler.Yul.YulStmt) (hStmts : BridgedStmts stmts) : execYulFuelWithBackend .verity fuel state (.stmts stmts) = @@ -2632,66 +1492,52 @@ theorem execYulFuelWithBackend_eq_on_bridged_stmts execYulFuelWithBackend_eq_on_bridged_target fuel state (.stmts stmts) (.stmts stmts hStmts) -theorem emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies +private theorem emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies (fuel : Nat) (state : YulState) (contract : Compiler.IRContract) - (hFunctions : ∀ fn, fn ∈ contract.functions → BridgedStmts fn.body) - (hFallback : ∀ fb, contract.fallbackEntrypoint = some fb → BridgedStmts fb.body) - (hReceive : ∀ rc, contract.receiveEntrypoint = some rc → BridgedStmts rc.body) - (hInternals : BridgedStmts contract.internalFunctions) : - execYulFuel fuel state (.stmts (Compiler.emitYul contract).runtimeCode) = + (_hFunctions : ∀ fn, fn ∈ contract.functions → BridgedStmts fn.body) + (_hFallback : ∀ fb, contract.fallbackEntrypoint = some fb → BridgedStmts fb.body) + (_hReceive : ∀ rc, contract.receiveEntrypoint = some rc → BridgedStmts rc.body) + (_hInternals : BridgedStmts contract.internalFunctions) : + legacyExecYulFuel fuel state (.stmts (Compiler.emitYul contract).runtimeCode) = execYulFuelWithBackend .evmYulLean fuel state (.stmts (Compiler.emitYul contract).runtimeCode) := by - rw [← execYulFuelWithBackend_verity_eq fuel state - (.stmts (Compiler.emitYul contract).runtimeCode)] - exact execYulFuelWithBackend_eq_on_bridged_target fuel state - (.stmts (Compiler.emitYul contract).runtimeCode) - (emitYul_runtimeCode_bridged contract hFunctions hFallback hReceive hInternals) + exact (execYulFuelWithBackend_evmYulLean_eq fuel state + (.stmts (Compiler.emitYul contract).runtimeCode)).symm -noncomputable def execYulStmtsWithBackend +private noncomputable def execYulStmtsWithBackend (backend : BuiltinBackend) (state : YulState) (stmts : List Compiler.Yul.YulStmt) : YulExecResult := execYulFuelWithBackend backend (sizeOf stmts + 1) state (.stmts stmts) -noncomputable def interpretYulRuntimeWithBackendFuel - (backend : BuiltinBackend) (fuel : Nat) - (runtimeCode : List Compiler.Yul.YulStmt) +private noncomputable def interpretYulRuntimeWithBackend + (backend : BuiltinBackend) (runtimeCode : List Compiler.Yul.YulStmt) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (events : List (List Nat) := []) : YulResult := let initialState := YulState.initial tx storage events yulResultOfExecWithRollback initialState - (execYulFuelWithBackend backend fuel initialState (.stmts runtimeCode)) + (execYulFuelWithBackend backend (sizeOf runtimeCode + 1) initialState + (.stmts runtimeCode)) -noncomputable def interpretYulRuntimeWithBackend - (backend : BuiltinBackend) (runtimeCode : List Compiler.Yul.YulStmt) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (events : List (List Nat) := []) : - YulResult := - interpretYulRuntimeWithBackendFuel backend (sizeOf runtimeCode + 1) - runtimeCode tx storage events - -@[simp] theorem interpretYulRuntimeWithBackend_eq_fuel - (backend : BuiltinBackend) (runtimeCode : List Compiler.Yul.YulStmt) - (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (events : List (List Nat) := []) : - interpretYulRuntimeWithBackend backend runtimeCode tx storage events = - interpretYulRuntimeWithBackendFuel backend (sizeOf runtimeCode + 1) - runtimeCode tx storage events := by - rfl +private noncomputable def interpretYulFromIR + (contract : Compiler.IRContract) + (tx : Compiler.Proofs.IRGeneration.IRTransaction) + (state : Compiler.Proofs.IRGeneration.IRState) : YulResult := + interpretYulRuntime (Compiler.emitYul contract).runtimeCode + (YulTransaction.ofIR tx) state.storage state.events -theorem interpretYulRuntimeWithBackend_verity_eq +private theorem interpretYulRuntimeWithBackend_evmYulLean_eq (runtimeCode : List Compiler.Yul.YulStmt) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (events : List (List Nat) := []) : - interpretYulRuntimeWithBackend .verity runtimeCode tx storage events = + interpretYulRuntimeWithBackend .evmYulLean runtimeCode tx storage events = interpretYulRuntime runtimeCode tx storage events := by - unfold interpretYulRuntimeWithBackend interpretYulRuntimeWithBackendFuel - interpretYulRuntime + unfold interpretYulRuntimeWithBackend interpretYulRuntime unfold execYulStmts execYulStmtsFuel change yulResultOfExecWithRollback (YulState.initial tx storage events) - (execYulFuelWithBackend .verity (sizeOf runtimeCode + 1) + (execYulFuelWithBackend .evmYulLean (sizeOf runtimeCode + 1) (YulState.initial tx storage events) (.stmts runtimeCode)) = - match execYulFuel (sizeOf runtimeCode + 1) + match legacyExecYulFuel (sizeOf runtimeCode + 1) (YulState.initial tx storage events) (.stmts runtimeCode) with | .continue s => { success := true, returnValue := s.returnValue, finalStorage := s.storage, @@ -2705,91 +1551,25 @@ theorem interpretYulRuntimeWithBackend_verity_eq | .revert _ => { success := false, returnValue := none, finalStorage := storage, finalMappings := Compiler.Proofs.storageAsMappings storage, events := events } - rw [execYulFuelWithBackend_verity_eq] - cases execYulFuel (sizeOf runtimeCode + 1) (YulState.initial tx storage events) + rw [execYulFuelWithBackend_evmYulLean_eq] + cases legacyExecYulFuel (sizeOf runtimeCode + 1) (YulState.initial tx storage events) (.stmts runtimeCode) <;> rfl -theorem interpretYulFromIR_evmYulLean_eq_on_bridged_bodies +private theorem interpretYulFromIR_evmYulLean_eq_on_bridged_bodies (contract : Compiler.IRContract) (tx : Compiler.Proofs.IRGeneration.IRTransaction) (state : Compiler.Proofs.IRGeneration.IRState) - (hFunctions : ∀ fn, fn ∈ contract.functions → BridgedStmts fn.body) - (hFallback : ∀ fb, contract.fallbackEntrypoint = some fb → BridgedStmts fb.body) - (hReceive : ∀ rc, contract.receiveEntrypoint = some rc → BridgedStmts rc.body) - (hInternals : BridgedStmts contract.internalFunctions) : - interpretYulFromIR contract tx state = + (_hFunctions : ∀ fn, fn ∈ contract.functions → BridgedStmts fn.body) + (_hFallback : ∀ fb, contract.fallbackEntrypoint = some fb → BridgedStmts fb.body) + (_hReceive : ∀ rc, contract.receiveEntrypoint = some rc → BridgedStmts rc.body) + (_hInternals : BridgedStmts contract.internalFunctions) : + interpretYulFromIR contract tx state = interpretYulRuntimeWithBackend .evmYulLean (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) state.storage state.events := by unfold interpretYulFromIR - calc - interpretYulRuntime (Compiler.emitYul contract).runtimeCode - (YulTransaction.ofIR tx) state.storage state.events = - interpretYulRuntimeWithBackend .verity - (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) - state.storage state.events := by - exact (interpretYulRuntimeWithBackend_verity_eq - (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) - state.storage (events := state.events)).symm - _ = interpretYulRuntimeWithBackend .evmYulLean - (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) - state.storage state.events := by - unfold interpretYulRuntimeWithBackend interpretYulRuntimeWithBackendFuel - change - yulResultOfExecWithRollback - (YulState.initial (YulTransaction.ofIR tx) state.storage state.events) - (execYulFuelWithBackend .verity - (sizeOf (Compiler.emitYul contract).runtimeCode + 1) - (YulState.initial (YulTransaction.ofIR tx) state.storage state.events) - (.stmts (Compiler.emitYul contract).runtimeCode)) = - yulResultOfExecWithRollback - (YulState.initial (YulTransaction.ofIR tx) state.storage state.events) - (execYulFuelWithBackend .evmYulLean - (sizeOf (Compiler.emitYul contract).runtimeCode + 1) - (YulState.initial (YulTransaction.ofIR tx) state.storage state.events) - (.stmts (Compiler.emitYul contract).runtimeCode)) - rw [execYulFuelWithBackend_verity_eq] - rw [emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies - (sizeOf (Compiler.emitYul contract).runtimeCode + 1) - (YulState.initial (YulTransaction.ofIR tx) state.storage state.events) - contract hFunctions hFallback hReceive hInternals] - -theorem yulCodegen_preserves_semantics_evmYulLean - (contract : Compiler.IRContract) - (tx : IRTransaction) - (initialState : IRState) - (hselector : tx.functionSelector < selectorModulus) - (hNoWrap : 4 + tx.args.length * 32 < evmModulus) - (hWF : ContractWF contract) - (hNoFallback : contract.fallbackEntrypoint = none) - (hNoReceive : contract.receiveEntrypoint = none) - (hdispatchGuardSafe : ∀ fn, fn ∈ contract.functions → - DispatchGuardsSafe fn tx) - (hNoHasSelector : ∀ fn, fn ∈ contract.functions → - yulStmtsNoRef "__has_selector" fn.body) - (hHasSelectorDead : ∀ fn, fn ∈ contract.functions → - HasSelectorDeadBridge fn.body) - (hLoopFree : ∀ fn, fn ∈ contract.functions → - yulStmtsLoopFree fn.body = true) - (hbody : ∀ fn, fn ∈ contract.functions → - resultsMatch - (execIRFunction fn tx.args (initialState.withTx tx)) - (interpretYulBody fn tx (initialState.withTx tx))) - (hFunctions : ∀ fn, fn ∈ contract.functions → BridgedStmts fn.body) - (hFallback : ∀ fb, contract.fallbackEntrypoint = some fb → BridgedStmts fb.body) - (hReceive : ∀ rc, contract.receiveEntrypoint = some rc → BridgedStmts rc.body) - (hInternals : BridgedStmts contract.internalFunctions) : - resultsMatch - (interpretIR contract tx initialState) - (interpretYulRuntimeWithBackend .evmYulLean - (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) - initialState.storage initialState.events) := by - have hLayer3 := - yulCodegen_preserves_semantics contract tx initialState - hselector hNoWrap hWF hNoFallback hNoReceive hdispatchGuardSafe - hNoHasSelector hHasSelectorDead hLoopFree hbody - rw [← interpretYulFromIR_evmYulLean_eq_on_bridged_bodies - contract tx initialState hFunctions hFallback hReceive hInternals] - exact hLayer3 + exact (interpretYulRuntimeWithBackend_evmYulLean_eq + (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) + state.storage (events := state.events)).symm /-! ## Phase 4 Completion Summary @@ -2802,7 +1582,7 @@ theorem yulCodegen_preserves_semantics_evmYulLean equivalence for `BridgedExpr`, covering literals, identifiers, nested calls to bridged builtins, and backend-independent `tload`/`mload`. 3. **Backend-parameterized statement executor**: `execYulFuelWithBackend` is a - backend-parameterized mirror of `execYulFuel`, providing the executor surface + backend-parameterized mirror of `legacyExecYulFuel`, providing the executor surface used by the statement-level equivalence proofs below. 4. **`execYulFuelWithBackend_{let,assign}_eq_on_bridged`**: First statement-level backend-equivalence theorems — `.let_ n v` and `.assign n v` @@ -2831,31 +1611,21 @@ theorem yulCodegen_preserves_semantics_evmYulLean `BridgedTarget`, whose nested statements satisfy `BridgedStmt`. 11. **`emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies`**: Composes emitted runtime-wrapper closure with recursive target equivalence to state - that Verity `execYulFuel` equals the EVMYulLean backend executor for + that Verity `legacyExecYulFuel` equals the EVMYulLean backend executor for `emitYul` runtime code when its embedded bodies are bridged. -12. **`yulCodegen_preserves_semantics_evmYulLean`**: Composes the existing - Layer-3 IR-to-Yul preservation theorem with the bridged-runtime equality - above, yielding a contract-level result whose Yul side is evaluated by the - EVMYulLean builtin backend. This lower-level theorem is intentionally - parameterized by generated embedded-body `BridgedStmts` witnesses; the - public safe-body EndToEnd wrapper derives those witnesses for supported - compiler-produced contracts. - -The public safe-body EndToEnd wrapper consumes this Layer-3 theorem after -deriving the raw `BridgedStmts` body witnesses from source-level -`BridgedSafeStmts` and static-parameter witnesses. The lower-level theorem here -intentionally remains useful for callers that already have explicit generated -Yul body witnesses. +12. The former contract-level EVMYulLean fuel-wrapper retarget theorem has + been removed from this module. The remaining facts are transition/regression + evidence for the bridged proof-interpreter fragment, while public + compiler-correctness theorems are expected to target native dispatcher + execution through `EvmYul.Yul.callDispatcher`. ### Trust boundary: Expressions constrained by `BridgedExpr`, straight-line statement lists constrained by `BridgedStraightStmts`, and recursive statement targets constrained by `BridgedTarget` inherit EVMYulLean semantics. Contract-level -Layer-3 preservation also targets the EVMYulLean backend when embedded bodies -satisfy `BridgedStmts`; the public safe-body EndToEnd theorem discharges those -raw body witnesses for supported compiler-produced contracts. The remaining -scope limit is the external-call/function-table family carved out by -`BridgedSafeStmts`. +proof-interpreter preservation is not exported from this module as public +compiler-correctness authority. The remaining scope limit is the +external-call/function-table family carved out by `BridgedSafeStmts`. -/ end Compiler.Proofs.YulGeneration.Backends diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSignedArithSpec.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSignedArithSpec.lean index 4b3198803..319ec056e 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSignedArithSpec.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSignedArithSpec.lean @@ -39,8 +39,8 @@ namespace SignedArithSpec /-- The 256-bit modulus used by the EVM, materialized as a Nat so the spec can live at the Nat level without dragging in `UInt256`/`Int256` -imports. Kept local to this module to avoid colliding with -`Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins.evmModulus`. -/ +imports. Kept local to this module to avoid colliding with the legacy +builtin module's modulus helper. -/ def specModulus : Nat := 2 ^ 256 /-- The 256-bit sign bit boundary: the smallest Nat whose top word-bit diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean index 1e2189885..03d58ad72 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean @@ -4,17 +4,37 @@ This module proves that the Verity compiler's `compileExpr` emits a `BridgedExpr` for the pure arithmetic / comparison / bit-operation fragment of the EDSL: - - scalar leaves: `literal`, `param`, `constructorArg`, `localVar` + - scalar/local leaves: `literal`, `param`, `constructorArg`, `localVar`, + `arrayLength` - pure binops whose Yul output is `yulBinOp NAME (← a) (← b)` with `NAME ∈ bridgedBuiltins`: `add`, `sub`, `mul`, `div`, `sdiv`, `mod`, `smod`, `bitAnd`, `bitOr`, `bitXor`, `shl`, `shr`, `sar`, `signextend`, `eq`, `gt`, `sgt`, `lt`, `slt` - negated comparisons via `yulNegatedBinOp`: `ge`, `le` + - boolean-normalized operations: `logicalAnd`, `logicalOr`, `logicalNot` + - branchless arithmetic helpers: `ceilDiv`, `mulDivDown`, `mulDivUp`, + `wMulDown`, `wDivUp`, `min`, `max`, `ite` + - reserved exponentiation builtin surface: + `externalCall builtinExpName [base, exponent]` + - zero-argument environment/calldata-size reads whose emitted Yul calls + are already bridged: `caller`, `contractAddress`, `msgValue`, + `blockTimestamp`, `blockNumber`, `chainid`, `blobbasefee`, + `calldatasize` + - storage reads whose compiler field lookup succeeds: `storage`, + `storageAddr`, `storageArrayLength`, `adtTag`, `adtField` + - singleton and nested mapping reads through the abstract `mappingSlot` + bridge: `mapping`, `mappingWord`, `mappingUint`, `mapping2`, + `mapping2Word` + - single-mapping struct-member reads through the same `mappingSlot` + bridge: `structMember`, `structMember2` + - unary calldata/memory/transient reads: `calldataload`, `mload`, `tload` + - native syntactic memory-slice hashing: `keccak256` - Storage, mapping, calldata, call, keccak256, dynamic helpers, - `bitNot`/`logicalAnd`/`logicalOr`/`logicalNot`/`min`/`max`/`ceilDiv`/ - `mulDivDown`/`mulDivUp`/`wMulDown`/`wDivUp`/`ite`/ABI casts are out - of scope and require dedicated closure proofs. + General external/internal calls, packed mapping entries, checked + dynamic-array elements, storage-array elements, ADT + construction/matching, returndata, dynamic helpers, ABI casts, + `selfBalance`, and external account/state reads are out of scope and require + dedicated closure proofs. The scalar-leaf-only theorem `compileExpr_bridgedSource_leaf` is retained below as a specialization. @@ -25,7 +45,8 @@ Run: lake build Compiler.Proofs.YulGeneration.Backends.EvmYulLeanSourceExprClosure -/ -import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanRetarget +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgePredicates +import Compiler.Proofs.IRGeneration.ExprCore import Compiler.CompilationModel.ExpressionCompile namespace Compiler.Proofs.YulGeneration.Backends @@ -33,6 +54,7 @@ namespace Compiler.Proofs.YulGeneration.Backends open Compiler open Compiler.Yul open Compiler.CompilationModel +open Compiler.Proofs.IRGeneration open Compiler.Proofs.YulGeneration /-- Scalar leaf expressions of the EDSL whose `compileExpr` output is a @@ -69,17 +91,77 @@ theorem compileExpr_bridgedSource_leaf exact BridgedExpr.ident name /-- Source EDSL expressions whose `compileExpr` output is a `BridgedExpr`. - Covers scalar leaves plus pure arithmetic/comparison/bit-op binops - that emit `yulBinOp NAME` for `NAME ∈ bridgedBuiltins`, plus `ge`/`le` - which emit `yulNegatedBinOp`. Storage, calldata, dynamic helpers, and - compound forms (bitNot/logicalAnd/logicalOr/logicalNot/min/max/ - ceilDiv/mulDiv*/wMul*/wDiv*/ite) are out of scope. -/ + Covers scalar/local leaves, storage reads whose compiler field lookup + succeeds, including dynamic-array length words and ADT tag/field reads, + singleton and nested mapping reads through the abstract `mappingSlot` + bridge, + mapping struct-member reads, + pure arithmetic/comparison/bit-op binops, boolean-normalization forms, + branchless arithmetic helpers, the reserved exponentiation builtin surface, + zero-argument environment/calldata-size reads, unary calldata/memory/ + transient reads, syntactic memory-slice `keccak256`, and `ge`/`le` negated + comparisons. General external/internal calls, packed mapping entries, + checked dynamic-array elements, storage-array elements, ADT + construction/matching, returndata, dynamic helpers, ABI casts, + `selfBalance`, and external account/state reads are out of scope. -/ inductive BridgedSourceExpr : Expr → Prop -- scalar leaves | literal (n : Nat) : BridgedSourceExpr (.literal n) | param (name : String) : BridgedSourceExpr (.param name) | constructorArg (idx : Nat) : BridgedSourceExpr (.constructorArg idx) | localVar (name : String) : BridgedSourceExpr (.localVar name) + | arrayLength (name : String) : BridgedSourceExpr (.arrayLength name) + -- storage reads + | storage (fieldName : String) : BridgedSourceExpr (.storage fieldName) + | storageAddr (fieldName : String) : BridgedSourceExpr (.storageAddr fieldName) + | storageArrayLength (fieldName : String) : + BridgedSourceExpr (.storageArrayLength fieldName) + | adtTag (adtName storageField : String) : + BridgedSourceExpr (.adtTag adtName storageField) + | adtField (adtName variantName fieldName : String) (fieldIndex : Nat) + (storageField : String) : + BridgedSourceExpr + (.adtField adtName variantName fieldName fieldIndex storageField) + | mapping {key : Expr} (fieldName : String) (hKey : BridgedSourceExpr key) : + BridgedSourceExpr (.mapping fieldName key) + | mappingWord {key : Expr} (fieldName : String) (hKey : BridgedSourceExpr key) + (wordOffset : Nat) : + BridgedSourceExpr (.mappingWord fieldName key wordOffset) + | mappingUint {key : Expr} (fieldName : String) (hKey : BridgedSourceExpr key) : + BridgedSourceExpr (.mappingUint fieldName key) + | mapping2 {key1 key2 : Expr} (fieldName : String) + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) : + BridgedSourceExpr (.mapping2 fieldName key1 key2) + | mapping2Word {key1 key2 : Expr} (fieldName : String) + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (wordOffset : Nat) : + BridgedSourceExpr (.mapping2Word fieldName key1 key2 wordOffset) + | structMember {key : Expr} (fieldName : String) (hKey : BridgedSourceExpr key) + (memberName : String) : + BridgedSourceExpr (.structMember fieldName key memberName) + | structMember2 {key1 key2 : Expr} (fieldName : String) + (hKey1 : BridgedSourceExpr key1) (hKey2 : BridgedSourceExpr key2) + (memberName : String) : + BridgedSourceExpr (.structMember2 fieldName key1 key2 memberName) + -- zero-argument environment / calldata-size reads + | caller : BridgedSourceExpr .caller + | contractAddress : BridgedSourceExpr .contractAddress + | msgValue : BridgedSourceExpr .msgValue + | blockTimestamp : BridgedSourceExpr .blockTimestamp + | blockNumber : BridgedSourceExpr .blockNumber + | chainid : BridgedSourceExpr .chainid + | blobbasefee : BridgedSourceExpr .blobbasefee + | calldatasize : BridgedSourceExpr .calldatasize + -- unary calldata / memory / transient reads + | calldataload {offset} (hOffset : BridgedSourceExpr offset) : + BridgedSourceExpr (.calldataload offset) + | mload {offset} (hOffset : BridgedSourceExpr offset) : + BridgedSourceExpr (.mload offset) + | tload {offset} (hOffset : BridgedSourceExpr offset) : + BridgedSourceExpr (.tload offset) + | keccak256 {offset size} + (hOffset : BridgedSourceExpr offset) (hSize : BridgedSourceExpr size) : + BridgedSourceExpr (.keccak256 offset size) -- arithmetic binops (yulBinOp with bridged name) | add {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : BridgedSourceExpr (.add a b) @@ -102,6 +184,8 @@ inductive BridgedSourceExpr : Expr → Prop BridgedSourceExpr (.bitOr a b) | bitXor {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : BridgedSourceExpr (.bitXor a b) + | bitNot {a} (ha : BridgedSourceExpr a) : + BridgedSourceExpr (.bitNot a) -- shift binops | shl {s v} (hs : BridgedSourceExpr s) (hv : BridgedSourceExpr v) : BridgedSourceExpr (.shl s v) @@ -122,12 +206,67 @@ inductive BridgedSourceExpr : Expr → Prop BridgedSourceExpr (.lt a b) | slt {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : BridgedSourceExpr (.slt a b) + -- boolean normalization + | logicalAnd {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : + BridgedSourceExpr (.logicalAnd a b) + | logicalOr {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : + BridgedSourceExpr (.logicalOr a b) + | logicalNot {a} (ha : BridgedSourceExpr a) : + BridgedSourceExpr (.logicalNot a) + -- branchless arithmetic helpers + | ceilDiv {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : + BridgedSourceExpr (.ceilDiv a b) + | mulDivDown {a b c} + (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) + (hc : BridgedSourceExpr c) : + BridgedSourceExpr (.mulDivDown a b c) + | mulDivUp {a b c} + (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) + (hc : BridgedSourceExpr c) : + BridgedSourceExpr (.mulDivUp a b c) + | wMulDown {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : + BridgedSourceExpr (.wMulDown a b) + | wDivUp {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : + BridgedSourceExpr (.wDivUp a b) + | builtinExp {base exponent} + (hBase : BridgedSourceExpr base) (hExponent : BridgedSourceExpr exponent) : + BridgedSourceExpr (.externalCall builtinExpName [base, exponent]) + | min {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : + BridgedSourceExpr (.min a b) + | max {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : + BridgedSourceExpr (.max a b) + | ite {cond thenVal elseVal} + (hCond : BridgedSourceExpr cond) (hThen : BridgedSourceExpr thenVal) + (hElse : BridgedSourceExpr elseVal) : + BridgedSourceExpr (.ite cond thenVal elseVal) -- negated comparisons (yulNegatedBinOp) | ge {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : BridgedSourceExpr (.ge a b) | le {a b} (ha : BridgedSourceExpr a) (hb : BridgedSourceExpr b) : BridgedSourceExpr (.le a b) +/-- The public IR compile-core expression grammar is contained in the native + source-expression bridge. This turns `SupportedFragment` expression + witnesses into the `BridgedSourceExpr` premises consumed by body-closure + proofs. -/ +theorem bridgedSourceExpr_of_exprCompileCore : + ∀ {e : Expr}, FunctionBody.ExprCompileCore e → BridgedSourceExpr e := by + intro e hCore + induction hCore <;> constructor <;> assumption + +/-- A syntactic memory-slice `keccak256` expression is native-bridged when its + offset and size arguments are in the public compile-core expression + grammar. This does not add `keccak256` to `ExprCompileCore`: source/IR + semantic correctness still needs source-side memory-slice hashing. -/ +theorem bridgedSourceExpr_keccak256_of_exprCompileCore + {offset size : Expr} + (hOffset : FunctionBody.ExprCompileCore offset) + (hSize : FunctionBody.ExprCompileCore size) : + BridgedSourceExpr (.keccak256 offset size) := + BridgedSourceExpr.keccak256 + (bridgedSourceExpr_of_exprCompileCore hOffset) + (bridgedSourceExpr_of_exprCompileCore hSize) + /-- A `YulExpr.call` whose name is in `bridgedBuiltins` and whose two arguments are already `BridgedExpr` is itself a `BridgedExpr`. -/ private theorem bridgedExpr_binopBuiltin {func : String} @@ -153,6 +292,15 @@ private theorem bridgedExpr_unopBuiltin {func : String} subst hMem exact ha +/-- A zero-argument `YulExpr.call` whose name is in `bridgedBuiltins` is a + `BridgedExpr`. -/ +private theorem bridgedExpr_nullaryBuiltin {func : String} + (hBridged : func ∈ bridgedBuiltins) : + BridgedExpr (YulExpr.call func []) := by + refine BridgedExpr.call func [] (Or.inl hBridged) ?_ + intro arg hMem + cases hMem + /-- `yulBinOp op a b` is bridged when `op ∈ bridgedBuiltins` and both arguments are bridged. -/ private theorem bridgedExpr_yulBinOp {func : String} @@ -172,10 +320,165 @@ private theorem bridgedExpr_yulNegatedBinOp {func : String} exact bridgedExpr_unopBuiltin (by simp [bridgedBuiltins]) (bridgedExpr_binopBuiltin hBridged ha hb) +/-- `yulToBool e = iszero(iszero(e))` is bridged when `e` is bridged. -/ +private theorem bridgedExpr_yulToBool {e : YulExpr} (hE : BridgedExpr e) : + BridgedExpr (yulToBool e) := by + unfold yulToBool + exact bridgedExpr_unopBuiltin (by simp [bridgedBuiltins]) + (bridgedExpr_unopBuiltin (by simp [bridgedBuiltins]) hE) + +private theorem bridgedExpr_ceilDiv {a b : YulExpr} + (ha : BridgedExpr a) (hb : BridgedExpr b) : + BridgedExpr + (YulExpr.call "mul" [ + YulExpr.call "iszero" [YulExpr.call "iszero" [a]], + YulExpr.call "add" [ + YulExpr.call "div" [YulExpr.call "sub" [a, YulExpr.lit 1], b], + YulExpr.lit 1 + ] + ]) := by + have hBool : BridgedExpr (YulExpr.call "iszero" [YulExpr.call "iszero" [a]]) := + bridgedExpr_yulToBool ha + have hSub : BridgedExpr (YulExpr.call "sub" [a, YulExpr.lit 1]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) ha (BridgedExpr.lit 1) + have hDiv : BridgedExpr (YulExpr.call "div" [YulExpr.call "sub" [a, YulExpr.lit 1], b]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hSub hb + have hAdd : + BridgedExpr + (YulExpr.call "add" [ + YulExpr.call "div" [YulExpr.call "sub" [a, YulExpr.lit 1], b], + YulExpr.lit 1]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hDiv (BridgedExpr.lit 1) + exact bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hBool hAdd + +private theorem bridgedExpr_mulDivDown {a b c : YulExpr} + (ha : BridgedExpr a) (hb : BridgedExpr b) (hc : BridgedExpr c) : + BridgedExpr (YulExpr.call "div" [YulExpr.call "mul" [a, b], c]) := by + exact bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) + (bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) ha hb) hc + +private theorem bridgedExpr_mulDivUp {a b c : YulExpr} + (ha : BridgedExpr a) (hb : BridgedExpr b) (hc : BridgedExpr c) : + BridgedExpr + (YulExpr.call "div" [ + YulExpr.call "add" [ + YulExpr.call "mul" [a, b], + YulExpr.call "sub" [c, YulExpr.lit 1] + ], + c + ]) := by + have hMul : BridgedExpr (YulExpr.call "mul" [a, b]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) ha hb + have hSub : BridgedExpr (YulExpr.call "sub" [c, YulExpr.lit 1]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hc (BridgedExpr.lit 1) + have hAdd : + BridgedExpr + (YulExpr.call "add" [ + YulExpr.call "mul" [a, b], + YulExpr.call "sub" [c, YulExpr.lit 1]]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hMul hSub + exact bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hAdd hc + +private theorem bridgedExpr_wMulDown {a b : YulExpr} + (ha : BridgedExpr a) (hb : BridgedExpr b) : + BridgedExpr + (YulExpr.call "div" [ + YulExpr.call "mul" [a, b], + YulExpr.lit 1000000000000000000]) := by + exact bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) + (bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) ha hb) + (BridgedExpr.lit 1000000000000000000) + +private theorem bridgedExpr_wDivUp {a b : YulExpr} + (ha : BridgedExpr a) (hb : BridgedExpr b) : + BridgedExpr + (YulExpr.call "div" [ + YulExpr.call "add" [ + YulExpr.call "mul" [a, YulExpr.lit 1000000000000000000], + YulExpr.call "sub" [b, YulExpr.lit 1] + ], + b + ]) := by + have hMul : + BridgedExpr + (YulExpr.call "mul" [a, YulExpr.lit 1000000000000000000]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) ha + (BridgedExpr.lit 1000000000000000000) + have hSub : BridgedExpr (YulExpr.call "sub" [b, YulExpr.lit 1]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hb (BridgedExpr.lit 1) + have hAdd : + BridgedExpr + (YulExpr.call "add" [ + YulExpr.call "mul" [a, YulExpr.lit 1000000000000000000], + YulExpr.call "sub" [b, YulExpr.lit 1]]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hMul hSub + exact bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hAdd hb + +private theorem bridgedExpr_min {a b : YulExpr} + (ha : BridgedExpr a) (hb : BridgedExpr b) : + BridgedExpr + (YulExpr.call "sub" [a, + YulExpr.call "mul" [ + YulExpr.call "sub" [a, b], + YulExpr.call "gt" [a, b] + ] + ]) := by + have hSub : BridgedExpr (YulExpr.call "sub" [a, b]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) ha hb + have hGt : BridgedExpr (YulExpr.call "gt" [a, b]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) ha hb + have hMul : + BridgedExpr + (YulExpr.call "mul" [YulExpr.call "sub" [a, b], YulExpr.call "gt" [a, b]]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hSub hGt + exact bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) ha hMul + +private theorem bridgedExpr_max {a b : YulExpr} + (ha : BridgedExpr a) (hb : BridgedExpr b) : + BridgedExpr + (YulExpr.call "add" [a, + YulExpr.call "mul" [ + YulExpr.call "sub" [b, a], + YulExpr.call "gt" [b, a] + ] + ]) := by + have hSub : BridgedExpr (YulExpr.call "sub" [b, a]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hb ha + have hGt : BridgedExpr (YulExpr.call "gt" [b, a]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hb ha + have hMul : + BridgedExpr + (YulExpr.call "mul" [YulExpr.call "sub" [b, a], YulExpr.call "gt" [b, a]]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hSub hGt + exact bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) ha hMul + +private theorem bridgedExpr_ite {cond thenVal elseVal : YulExpr} + (hCond : BridgedExpr cond) (hThen : BridgedExpr thenVal) + (hElse : BridgedExpr elseVal) : + BridgedExpr + (YulExpr.call "add" [ + YulExpr.call "mul" [ + YulExpr.call "iszero" [YulExpr.call "iszero" [cond]], thenVal], + YulExpr.call "mul" [YulExpr.call "iszero" [cond], elseVal] + ]) := by + have hBool : BridgedExpr (YulExpr.call "iszero" [YulExpr.call "iszero" [cond]]) := + bridgedExpr_yulToBool hCond + have hNeg : BridgedExpr (YulExpr.call "iszero" [cond]) := + bridgedExpr_unopBuiltin (by simp [bridgedBuiltins]) hCond + have hThenTerm : + BridgedExpr + (YulExpr.call "mul" [ + YulExpr.call "iszero" [YulExpr.call "iszero" [cond]], thenVal]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hBool hThen + have hElseTerm : + BridgedExpr (YulExpr.call "mul" [YulExpr.call "iszero" [cond], elseVal]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hNeg hElse + exact bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hThenTerm hElseTerm + /-- Destructure a `do`-block emission of `yulBinOp` into its sub-results. This shape matches what `simp only [compileExpr]` produces for every binop constructor case. -/ -private lemma compileExpr_yulBinOp_ok +private theorem compileExpr_yulBinOp_ok {fields : List CompilationModel.Field} {src : DynamicDataSource} {op : String} {a b : Expr} {out : YulExpr} (hOk : (do let x ← compileExpr fields src a @@ -195,7 +498,7 @@ private lemma compileExpr_yulBinOp_ok exact hOk.symm /-- Same destructuring for `yulNegatedBinOp` emissions (used by `ge`/`le`). -/ -private lemma compileExpr_yulNegatedBinOp_ok +private theorem compileExpr_yulNegatedBinOp_ok {fields : List CompilationModel.Field} {src : DynamicDataSource} {op : String} {a b : Expr} {out : YulExpr} (hOk : (do let x ← compileExpr fields src a @@ -214,6 +517,286 @@ private lemma compileExpr_yulNegatedBinOp_ok simp [hA, hB, bind, Except.bind, Pure.pure, Except.pure] at hOk exact hOk.symm +/-- Destructure a boolean-normalized binary expression emission. -/ +private theorem compileExpr_yulBoolBinOp_ok + {fields : List CompilationModel.Field} {src : DynamicDataSource} + {op : String} {a b : Expr} {out : YulExpr} + (hOk : (do let x ← compileExpr fields src a + let y ← compileExpr fields src b + pure (yulBinOp op (yulToBool x) (yulToBool y)) : + Except String YulExpr) = .ok out) : + ∃ ca cb, compileExpr fields src a = .ok ca + ∧ compileExpr fields src b = .ok cb + ∧ out = yulBinOp op (yulToBool ca) (yulToBool cb) := by + cases hA : compileExpr fields src a with + | error e => simp [hA, bind, Except.bind] at hOk + | ok ca => + cases hB : compileExpr fields src b with + | error e => simp [hA, hB, bind, Except.bind] at hOk + | ok cb => + refine ⟨ca, cb, rfl, rfl, ?_⟩ + simp [hA, hB, bind, Except.bind, Pure.pure, Except.pure] at hOk + exact hOk.symm + +/-- Destructure a unary builtin expression emission. -/ +private theorem compileExpr_unopBuiltin_ok + {fields : List CompilationModel.Field} {src : DynamicDataSource} + {op : String} {a : Expr} {out : YulExpr} + (hOk : (do let x ← compileExpr fields src a + pure (YulExpr.call op [x]) : Except String YulExpr) = .ok out) : + ∃ ca, compileExpr fields src a = .ok ca ∧ out = YulExpr.call op [ca] := by + cases hA : compileExpr fields src a with + | error e => simp [hA, bind, Except.bind] at hOk + | ok ca => + refine ⟨ca, rfl, ?_⟩ + simp [hA, bind, Except.bind, Pure.pure, Except.pure] at hOk + exact hOk.symm + +/-- Literal-slot `sload` is in the native bridged expression fragment. -/ +private theorem bridgedExpr_sload_lit (slot : Nat) : + BridgedExpr (YulExpr.call "sload" [YulExpr.lit slot]) := by + refine BridgedExpr.call "sload" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_singleton] at hMem + subst arg + exact BridgedExpr.lit slot + +/-- `sload(e)` is in the native bridged expression fragment whenever the slot + expression is bridged. -/ +private theorem bridgedExpr_sload {slot : YulExpr} (hSlot : BridgedExpr slot) : + BridgedExpr (YulExpr.call "sload" [slot]) := by + refine BridgedExpr.call "sload" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_singleton] at hMem + subst arg + exact hSlot + +/-- `mappingSlot(base, key)` is in the native bridged expression fragment + whenever both slot arguments are bridged. -/ +private theorem bridgedExpr_mappingSlot {base key : YulExpr} + (hBase : BridgedExpr base) (hKey : BridgedExpr key) : + BridgedExpr (YulExpr.call "mappingSlot" [base, key]) := + bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) hBase hKey + +/-- `sload(mappingSlot(lit slot, key))` is bridged for bridged keys. -/ +private theorem bridgedExpr_sload_mappingSlot_lit + (slot : Nat) {key : YulExpr} (hKey : BridgedExpr key) : + BridgedExpr + (YulExpr.call "sload" + [YulExpr.call "mappingSlot" [YulExpr.lit slot, key]]) := + bridgedExpr_sload + (bridgedExpr_mappingSlot (BridgedExpr.lit slot) hKey) + +/-- `sload(add(mappingSlot(lit slot, key), lit wordOffset))` is bridged for + bridged keys. -/ +private theorem bridgedExpr_sload_mappingSlot_lit_add + (slot wordOffset : Nat) {key : YulExpr} (hKey : BridgedExpr key) : + BridgedExpr + (YulExpr.call "sload" + [YulExpr.call "add" + [YulExpr.call "mappingSlot" [YulExpr.lit slot, key], + YulExpr.lit wordOffset]]) := + bridgedExpr_sload + (bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) + (bridgedExpr_mappingSlot (BridgedExpr.lit slot) hKey) + (BridgedExpr.lit wordOffset)) + +/-- `sload(mappingSlot(mappingSlot(lit slot, key1), key2))` is bridged for + bridged nested mapping keys. -/ +private theorem bridgedExpr_sload_mappingSlot2_lit + (slot : Nat) {key1 key2 : YulExpr} + (hKey1 : BridgedExpr key1) (hKey2 : BridgedExpr key2) : + BridgedExpr + (YulExpr.call "sload" + [YulExpr.call "mappingSlot" + [YulExpr.call "mappingSlot" [YulExpr.lit slot, key1], key2]]) := + bridgedExpr_sload + (bridgedExpr_mappingSlot + (bridgedExpr_mappingSlot (BridgedExpr.lit slot) hKey1) + hKey2) + +/-- `sload(add(mappingSlot(mappingSlot(lit slot, key1), key2), lit + wordOffset))` is bridged for bridged nested mapping keys. -/ +private theorem bridgedExpr_sload_mappingSlot2_lit_add + (slot wordOffset : Nat) {key1 key2 : YulExpr} + (hKey1 : BridgedExpr key1) (hKey2 : BridgedExpr key2) : + BridgedExpr + (YulExpr.call "sload" + [YulExpr.call "add" + [YulExpr.call "mappingSlot" + [YulExpr.call "mappingSlot" [YulExpr.lit slot, key1], key2], + YulExpr.lit wordOffset]]) := + bridgedExpr_sload + (bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) + (bridgedExpr_mappingSlot + (bridgedExpr_mappingSlot (BridgedExpr.lit slot) hKey1) + hKey2) + (BridgedExpr.lit wordOffset)) + +/-- A `foldl mappingSlot` chain over bridged key expressions stays in the + native bridged expression fragment. -/ +private theorem bridgedExpr_foldl_mappingSlot + (keys : List YulExpr) {base : YulExpr} + (hBase : BridgedExpr base) + (hKeys : ∀ key ∈ keys, BridgedExpr key) : + BridgedExpr + (keys.foldl + (fun slotExpr keyExpr => + YulExpr.call "mappingSlot" [slotExpr, keyExpr]) + base) := by + induction keys generalizing base with + | nil => + simpa using hBase + | cons key rest ih => + simp only [List.foldl_cons] + have hKey : BridgedExpr key := hKeys key (by simp) + have hRest : ∀ k ∈ rest, BridgedExpr k := by + intro k hk + exact hKeys k (by simp [hk]) + exact ih (bridgedExpr_mappingSlot hBase hKey) hRest + +/-- `sload(compileMappingSlotChain(lit slot, keys))` is bridged when every + compiled key is bridged. -/ +private theorem bridgedExpr_sload_mappingSlotChain_lit + (slot : Nat) (keys : List YulExpr) + (hKeys : ∀ key ∈ keys, BridgedExpr key) : + BridgedExpr + (YulExpr.call "sload" + [compileMappingSlotChain (YulExpr.lit slot) keys]) := by + unfold compileMappingSlotChain + exact bridgedExpr_sload + (bridgedExpr_foldl_mappingSlot keys (BridgedExpr.lit slot) hKeys) + +/-- The compiler's singleton mapping-read helper emits only native-bridged + Yul when field lookup succeeds and the key expression is bridged. + + The proof intentionally stays at the `mappingSlot` helper boundary; it does + not claim source-level memory+keccak equivalence for mapping slots. -/ +private theorem compileMappingSlotRead_bridged + {fields : List CompilationModel.Field} {field label : String} + {keyExpr out : YulExpr} {wordOffset : Nat} + (hKey : BridgedExpr keyExpr) + (hOk : + compileMappingSlotRead fields field keyExpr label wordOffset = .ok out) : + BridgedExpr out := by + unfold compileMappingSlotRead at hOk + split at hOk + · simp at hOk + · split at hOk + · rename_i slot hFind + dsimp at hOk + split at hOk + · simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_mappingSlot_lit slot hKey + · simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_mappingSlot_lit_add slot wordOffset hKey + · simp at hOk + +/-- ADT tag reads compile to `and(sload(baseSlot), 0xff)`. -/ +private theorem bridgedExpr_adtTagRead_lit (baseSlot : Nat) : + BridgedExpr (compileAdtTagRead (YulExpr.lit baseSlot)) := by + unfold compileAdtTagRead + exact bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) + (bridgedExpr_sload_lit baseSlot) (BridgedExpr.lit 0xFF) + +/-- ADT field reads compile to `sload(add(baseSlot, fieldIndex + 1))`. -/ +private theorem bridgedExpr_adtFieldRead_lit (baseSlot fieldIndex : Nat) : + BridgedExpr (compileAdtFieldRead (YulExpr.lit baseSlot) fieldIndex) := by + unfold compileAdtFieldRead + exact bridgedExpr_sload + (bridgedExpr_binopBuiltin (by simp [bridgedBuiltins]) + (BridgedExpr.lit baseSlot) (BridgedExpr.lit (fieldIndex + 1))) + +/-- Packed storage reads compile to `and(shr(offset, sload(slot)), mask)`, + whose subexpressions are all native bridged builtins. -/ +private theorem bridgedExpr_packed_sload_lit + (slot offset mask : Nat) : + BridgedExpr + (YulExpr.call "and" + [YulExpr.call "shr" [YulExpr.lit offset, + YulExpr.call "sload" [YulExpr.lit slot]], + YulExpr.lit mask]) := by + refine BridgedExpr.call "and" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_cons, List.mem_nil_iff, or_false] at hMem + rcases hMem with rfl | rfl + · refine BridgedExpr.call "shr" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_cons, List.mem_nil_iff, or_false] at hMem + rcases hMem with rfl | rfl + · exact BridgedExpr.lit offset + · exact bridgedExpr_sload_lit slot + · exact BridgedExpr.lit mask + +/-- Packed reads over an already-bridged slot word compile to + `and(shr(offset, slotWord), mask)`, whose subexpressions are bridged. -/ +private theorem bridgedExpr_packed_read + {slotWord : YulExpr} (hSlotWord : BridgedExpr slotWord) + (offset mask : Nat) : + BridgedExpr + (YulExpr.call "and" + [YulExpr.call "shr" [YulExpr.lit offset, slotWord], + YulExpr.lit mask]) := by + refine BridgedExpr.call "and" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_cons, List.mem_nil_iff, or_false] at hMem + rcases hMem with rfl | rfl + · refine BridgedExpr.call "shr" _ (Or.inl (by simp [bridgedBuiltins])) ?_ + intro arg hMem + simp only [List.mem_cons, List.mem_nil_iff, or_false] at hMem + rcases hMem with rfl | rfl + · exact BridgedExpr.lit offset + · exact hSlotWord + · exact BridgedExpr.lit mask + +/-- Destructure a binary helper expression emission. -/ +private theorem compileExpr_binaryShape_ok + {fields : List CompilationModel.Field} {src : DynamicDataSource} + {shape : YulExpr → YulExpr → YulExpr} {a b : Expr} {out : YulExpr} + (hOk : (do let x ← compileExpr fields src a + let y ← compileExpr fields src b + pure (shape x y) : Except String YulExpr) = .ok out) : + ∃ ca cb, compileExpr fields src a = .ok ca + ∧ compileExpr fields src b = .ok cb + ∧ out = shape ca cb := by + cases hA : compileExpr fields src a with + | error e => simp [hA, bind, Except.bind] at hOk + | ok ca => + cases hB : compileExpr fields src b with + | error e => simp [hA, hB, bind, Except.bind] at hOk + | ok cb => + refine ⟨ca, cb, rfl, rfl, ?_⟩ + simp [hA, hB, bind, Except.bind, Pure.pure, Except.pure] at hOk + exact hOk.symm + +/-- Destructure a ternary helper expression emission. -/ +private theorem compileExpr_ternaryShape_ok + {fields : List CompilationModel.Field} {src : DynamicDataSource} + {shape : YulExpr → YulExpr → YulExpr → YulExpr} + {a b c : Expr} {out : YulExpr} + (hOk : (do let x ← compileExpr fields src a + let y ← compileExpr fields src b + let z ← compileExpr fields src c + pure (shape x y z) : Except String YulExpr) = .ok out) : + ∃ ca cb cc, compileExpr fields src a = .ok ca + ∧ compileExpr fields src b = .ok cb + ∧ compileExpr fields src c = .ok cc + ∧ out = shape ca cb cc := by + cases hA : compileExpr fields src a with + | error e => simp [hA, bind, Except.bind] at hOk + | ok ca => + cases hB : compileExpr fields src b with + | error e => simp [hA, hB, bind, Except.bind] at hOk + | ok cb => + cases hC : compileExpr fields src c with + | error e => simp [hA, hB, hC, bind, Except.bind] at hOk + | ok cc => + refine ⟨ca, cb, cc, rfl, rfl, rfl, ?_⟩ + simp [hA, hB, hC, bind, Except.bind, Pure.pure, Except.pure] at hOk + exact hOk.symm + /-- Main theorem: every `BridgedSourceExpr` compiles to a `BridgedExpr`. Structural induction on the source predicate. Binop cases delegate to `compileExpr_yulBinOp_ok` / `compileExpr_yulNegatedBinOp_ok` to @@ -241,6 +824,333 @@ theorem compileExpr_bridgedSource intro out hOk simp [compileExpr, Pure.pure, Except.pure] at hOk subst out; exact BridgedExpr.ident name + | arrayLength name => + intro out hOk + simp [compileExpr, Pure.pure, Except.pure] at hOk + subst out; exact BridgedExpr.ident s!"{name}_length" + | storage fieldName => + intro out hOk + simp only [compileExpr] at hOk + split at hOk + · simp at hOk + · split at hOk + · rename_i f slot hFind + cases hPacked : f.packedBits with + | none => + simp [hPacked, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_lit slot + | some packed => + simp [hPacked, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_packed_sload_lit slot packed.offset + (packedMaskNat packed) + · simp at hOk + | storageAddr fieldName => + intro out hOk + simp only [compileExpr] at hOk + split at hOk + · simp at hOk + · split at hOk + · rename_i f slot hFind + cases hTy : f.ty with + | address => + cases hPacked : f.packedBits with + | none => + simp [hTy, hPacked, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_lit slot + | some packed => + simp [hTy, hPacked, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_packed_sload_lit slot packed.offset + (packedMaskNat packed) + | uint256 | dynamicArray | mappingTyped | mappingStruct + | mappingStruct2 | adt => + simp [hTy] at hOk + · simp at hOk + | storageArrayLength fieldName => + intro out hOk + simp only [compileExpr] at hOk + split at hOk + · rename_i f slot hFind + cases hTy : f.ty with + | dynamicArray elemTy => + simp [hTy, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_lit slot + | uint256 | address | mappingTyped | mappingStruct | mappingStruct2 | adt => + simp [hTy] at hOk + · simp at hOk + | adtTag adtName storageField => + intro out hOk + simp only [compileExpr] at hOk + split at hOk + · rename_i baseSlot hFind + simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_adtTagRead_lit baseSlot + · simp at hOk + | adtField adtName variantName fieldName fieldIndex storageField => + intro out hOk + simp only [compileExpr] at hOk + split at hOk + · rename_i baseSlot hFind + simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_adtFieldRead_lit baseSlot fieldIndex + · simp at hOk + | mapping fieldName hKey ihKey => + intro out hOk + simp only [compileExpr, bind, Except.bind] at hOk + cases hCompiledKey : compileExpr fields src _ with + | error err => + rw [hCompiledKey] at hOk + cases hOk + | ok keyExpr => + rw [hCompiledKey] at hOk + exact compileMappingSlotRead_bridged (ihKey hCompiledKey) hOk + | mappingWord fieldName hKey wordOffset ihKey => + intro out hOk + simp only [compileExpr, bind, Except.bind] at hOk + cases hCompiledKey : compileExpr fields src _ with + | error err => + rw [hCompiledKey] at hOk + cases hOk + | ok keyExpr => + rw [hCompiledKey] at hOk + exact compileMappingSlotRead_bridged (ihKey hCompiledKey) hOk + | mappingUint fieldName hKey ihKey => + intro out hOk + simp only [compileExpr, bind, Except.bind] at hOk + cases hCompiledKey : compileExpr fields src _ with + | error err => + rw [hCompiledKey] at hOk + cases hOk + | ok keyExpr => + rw [hCompiledKey] at hOk + exact compileMappingSlotRead_bridged (ihKey hCompiledKey) hOk + | mapping2 fieldName hKey1 hKey2 ihKey1 ihKey2 => + intro out hOk + simp only [compileExpr] at hOk + split at hOk + · simp at hOk + · split at hOk + · rename_i slot hFind + simp only [bind, Except.bind] at hOk + cases hCompiledKey1 : compileExpr fields src _ with + | error err => + rw [hCompiledKey1] at hOk + cases hOk + | ok keyExpr1 => + rw [hCompiledKey1] at hOk + cases hCompiledKey2 : compileExpr fields src _ with + | error err => + rw [hCompiledKey2] at hOk + cases hOk + | ok keyExpr2 => + rw [hCompiledKey2] at hOk + simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_mappingSlot2_lit slot + (ihKey1 hCompiledKey1) (ihKey2 hCompiledKey2) + · simp at hOk + | mapping2Word fieldName hKey1 hKey2 wordOffset ihKey1 ihKey2 => + intro out hOk + simp only [compileExpr] at hOk + split at hOk + · simp at hOk + · split at hOk + · rename_i slot hFind + simp only [bind, Except.bind] at hOk + cases hCompiledKey1 : compileExpr fields src _ with + | error err => + rw [hCompiledKey1] at hOk + cases hOk + | ok keyExpr1 => + rw [hCompiledKey1] at hOk + cases hCompiledKey2 : compileExpr fields src _ with + | error err => + rw [hCompiledKey2] at hOk + cases hOk + | ok keyExpr2 => + rw [hCompiledKey2] at hOk + dsimp at hOk + split at hOk + · simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_mappingSlot2_lit slot + (ihKey1 hCompiledKey1) (ihKey2 hCompiledKey2) + · simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_mappingSlot2_lit_add slot wordOffset + (ihKey1 hCompiledKey1) (ihKey2 hCompiledKey2) + · simp at hOk + | structMember fieldName hKey memberName ihKey => + intro out hOk + simp [compileExpr, bind, Except.bind] at hOk + split at hOk + · cases hOk + · simp [Pure.pure, Except.pure] at hOk + split at hOk + · simp at hOk + · split at hOk + · simp at hOk + · rename_i member hMember + cases hPacked : member.packed with + | none => + rw [hPacked] at hOk + cases hCompiledKey : compileExpr fields src _ with + | error err => + rw [hCompiledKey] at hOk + cases hOk + | ok keyExpr => + rw [hCompiledKey] at hOk + simp at hOk + exact compileMappingSlotRead_bridged (ihKey hCompiledKey) hOk + | some packed => + rw [hPacked] at hOk + cases hCompiledKey : compileExpr fields src _ with + | error err => + rw [hCompiledKey] at hOk + cases hOk + | ok keyExpr => + rw [hCompiledKey] at hOk + simp at hOk + cases hSlotWord : + compileMappingSlotRead fields fieldName keyExpr + s!"structMember.{memberName}" member.wordOffset with + | error err => + rw [hSlotWord] at hOk + cases hOk + | ok slotWord => + rw [hSlotWord] at hOk + simp at hOk + subst out + exact bridgedExpr_packed_read + (compileMappingSlotRead_bridged + (ihKey hCompiledKey) hSlotWord) + packed.offset (packedMaskNat packed) + | structMember2 fieldName hKey1 hKey2 memberName ihKey1 ihKey2 => + intro out hOk + simp [compileExpr, bind, Except.bind] at hOk + split at hOk + · cases hOk + · split at hOk + · simp at hOk + · split at hOk + · simp at hOk + · rename_i member hMember + split at hOk + · rename_i slot hFindSlot + cases hCompiledKey1 : compileExpr fields src _ with + | error err => + rw [hCompiledKey1] at hOk + cases hOk + | ok keyExpr1 => + rw [hCompiledKey1] at hOk + cases hCompiledKey2 : compileExpr fields src _ with + | error err => + rw [hCompiledKey2] at hOk + cases hOk + | ok keyExpr2 => + rw [hCompiledKey2] at hOk + cases hPacked : member.packed with + | none => + rw [hPacked] at hOk + simp at hOk + split at hOk + · simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_mappingSlot2_lit slot + (ihKey1 hCompiledKey1) (ihKey2 hCompiledKey2) + · simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_mappingSlot2_lit_add slot + member.wordOffset + (ihKey1 hCompiledKey1) (ihKey2 hCompiledKey2) + | some packed => + rw [hPacked] at hOk + simp at hOk + split at hOk + · simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_packed_read + (bridgedExpr_sload_mappingSlot2_lit slot + (ihKey1 hCompiledKey1) (ihKey2 hCompiledKey2)) + packed.offset (packedMaskNat packed) + · simp [Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_packed_read + (bridgedExpr_sload_mappingSlot2_lit_add slot + member.wordOffset + (ihKey1 hCompiledKey1) (ihKey2 hCompiledKey2)) + packed.offset (packedMaskNat packed) + · simp at hOk + | caller => + intro out hOk + simp [compileExpr, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_nullaryBuiltin (by simp [bridgedBuiltins]) + | contractAddress => + intro out hOk + simp [compileExpr, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_nullaryBuiltin (by simp [bridgedBuiltins]) + | msgValue => + intro out hOk + simp [compileExpr, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_nullaryBuiltin (by simp [bridgedBuiltins]) + | blockTimestamp => + intro out hOk + simp [compileExpr, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_nullaryBuiltin (by simp [bridgedBuiltins]) + | blockNumber => + intro out hOk + simp [compileExpr, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_nullaryBuiltin (by simp [bridgedBuiltins]) + | chainid => + intro out hOk + simp [compileExpr, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_nullaryBuiltin (by simp [bridgedBuiltins]) + | blobbasefee => + intro out hOk + simp [compileExpr, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_nullaryBuiltin (by simp [bridgedBuiltins]) + | calldatasize => + intro out hOk + simp [compileExpr, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_nullaryBuiltin (by simp [bridgedBuiltins]) + | calldataload _ iho => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨co, hO, hEq⟩ := compileExpr_unopBuiltin_ok hOk + subst hEq + exact bridgedExpr_unopBuiltin (by simp [bridgedBuiltins]) (iho hO) + | mload _ iho => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨co, hO, hEq⟩ := compileExpr_unopBuiltin_ok hOk + subst hEq + exact bridgedExpr_mload co (iho hO) + | tload _ iho => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨co, hO, hEq⟩ := compileExpr_unopBuiltin_ok hOk + subst hEq + exact bridgedExpr_tload co (iho hO) + | keccak256 _ _ ihOffset ihSize => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨co, cs, hO, hS, hEq⟩ := compileExpr_binaryShape_ok hOk + subst hEq + exact bridgedExpr_keccak256 co cs (ihOffset hO) (ihSize hS) | add _ _ iha ihb => intro out hOk simp only [compileExpr] at hOk @@ -301,6 +1211,12 @@ theorem compileExpr_bridgedSource obtain ⟨ca, cb, hA, hB, hEq⟩ := compileExpr_yulBinOp_ok hOk subst hEq exact bridgedExpr_yulBinOp (by simp [bridgedBuiltins]) (iha hA) (ihb hB) + | bitNot _ iha => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, hA, hEq⟩ := compileExpr_unopBuiltin_ok hOk + subst hEq + exact bridgedExpr_unopBuiltin (by simp [bridgedBuiltins]) (iha hA) | shl _ _ ihs ihv => intro out hOk simp only [compileExpr] at hOk @@ -355,6 +1271,91 @@ theorem compileExpr_bridgedSource obtain ⟨ca, cb, hA, hB, hEq⟩ := compileExpr_yulBinOp_ok hOk subst hEq exact bridgedExpr_yulBinOp (by simp [bridgedBuiltins]) (iha hA) (ihb hB) + | logicalAnd _ _ iha ihb => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, cb, hA, hB, hEq⟩ := compileExpr_yulBoolBinOp_ok hOk + subst hEq + exact bridgedExpr_yulBinOp (by simp [bridgedBuiltins]) + (bridgedExpr_yulToBool (iha hA)) (bridgedExpr_yulToBool (ihb hB)) + | logicalOr _ _ iha ihb => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, cb, hA, hB, hEq⟩ := compileExpr_yulBoolBinOp_ok hOk + subst hEq + exact bridgedExpr_yulBinOp (by simp [bridgedBuiltins]) + (bridgedExpr_yulToBool (iha hA)) (bridgedExpr_yulToBool (ihb hB)) + | logicalNot _ iha => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, hA, hEq⟩ := compileExpr_unopBuiltin_ok hOk + subst hEq + exact bridgedExpr_unopBuiltin (by simp [bridgedBuiltins]) (iha hA) + | ceilDiv _ _ iha ihb => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, cb, hA, hB, hEq⟩ := compileExpr_binaryShape_ok hOk + subst hEq + exact bridgedExpr_ceilDiv (iha hA) (ihb hB) + | mulDivDown _ _ _ iha ihb ihc => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, cb, cc, hA, hB, hC, hEq⟩ := compileExpr_ternaryShape_ok hOk + subst hEq + exact bridgedExpr_mulDivDown (iha hA) (ihb hB) (ihc hC) + | mulDivUp _ _ _ iha ihb ihc => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, cb, cc, hA, hB, hC, hEq⟩ := compileExpr_ternaryShape_ok hOk + subst hEq + exact bridgedExpr_mulDivUp (iha hA) (ihb hB) (ihc hC) + | wMulDown _ _ iha ihb => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, cb, hA, hB, hEq⟩ := compileExpr_binaryShape_ok hOk + subst hEq + exact bridgedExpr_wMulDown (iha hA) (ihb hB) + | wDivUp _ _ iha ihb => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, cb, hA, hB, hEq⟩ := compileExpr_binaryShape_ok hOk + subst hEq + exact bridgedExpr_wDivUp (iha hA) (ihb hB) + | builtinExp hBase hExponent iha ihb => + rename_i base exponent + intro out hOk + simp only [compileExpr] at hOk + cases hA : compileExpr fields src base with + | error err => + simp [compileExprList, hA, bind, Except.bind] at hOk + | ok ca => + cases hB : compileExpr fields src exponent with + | error err => + simp [compileExprList, hA, hB, bind, Except.bind] at hOk + | ok cb => + simp [compileExprList, hA, hB, builtinExpName, Pure.pure, + Except.pure, bind, Except.bind] at hOk + cases hOk + exact bridgedExpr_yulBinOp (by simp [bridgedBuiltins]) + (iha hA) (ihb hB) + | min _ _ iha ihb => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, cb, hA, hB, hEq⟩ := compileExpr_binaryShape_ok hOk + subst hEq + exact bridgedExpr_min (iha hA) (ihb hB) + | max _ _ iha ihb => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨ca, cb, hA, hB, hEq⟩ := compileExpr_binaryShape_ok hOk + subst hEq + exact bridgedExpr_max (iha hA) (ihb hB) + | ite _ _ _ ihc iht ihe => + intro out hOk + simp only [compileExpr] at hOk + obtain ⟨cc, ct, ce, hC, hT, hE, hEq⟩ := compileExpr_ternaryShape_ok hOk + subst hEq + exact bridgedExpr_ite (ihc hC) (iht hT) (ihe hE) | ge _ _ iha ihb => intro out hOk simp only [compileExpr] at hOk @@ -368,9 +1369,22 @@ theorem compileExpr_bridgedSource subst hEq exact bridgedExpr_yulNegatedBinOp (by simp [bridgedBuiltins]) (iha hA) (ihb hB) +/-- Convenience wrapper for the native syntactic `keccak256` source-expression + closure when the offset and size subexpressions are compile-core. -/ +theorem compileExpr_keccak256_bridgedSource_of_exprCompileCore + (fields : List CompilationModel.Field) (src : DynamicDataSource) + {offset size : Expr} {out : YulExpr} + (hOffset : FunctionBody.ExprCompileCore offset) + (hSize : FunctionBody.ExprCompileCore size) + (hOk : compileExpr fields src (.keccak256 offset size) = .ok out) : + BridgedExpr out := + compileExpr_bridgedSource fields src + (bridgedSourceExpr_keccak256_of_exprCompileCore hOffset hSize) + hOk + /-- Default `require` failure condition shape: `iszero(compileExpr cond)` is bridged whenever the source condition expression is bridged. -/ -private lemma compileRequireFailCond_default_bridgedSource +private theorem compileRequireFailCond_default_bridgedSource {fields : List CompilationModel.Field} {src : DynamicDataSource} {cond : Expr} {failCond : YulExpr} (hCond : BridgedSourceExpr cond) @@ -382,11 +1396,10 @@ private lemma compileRequireFailCond_default_bridgedSource cases hCompiled : compileExpr fields src cond with | error err => rw [hCompiled] at hOk - simp at hOk + cases hOk | ok compiled => rw [hCompiled] at hOk - simp at hOk - subst hOk + cases hOk exact bridgedExpr_unopBuiltin (by simp [bridgedBuiltins]) (compileExpr_bridgedSource fields src hCond hCompiled) @@ -400,6 +1413,43 @@ theorem compileRequireFailCond_bridgedSource compileRequireFailCond fields src cond = .ok failCond → BridgedExpr failCond := by intro cond hCond failCond hOk cases hCond with + | storage fieldName => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.storage fieldName) hOk + | storageAddr fieldName => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.storageAddr fieldName) hOk + | storageArrayLength fieldName => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.storageArrayLength fieldName) hOk + | adtTag adtName storageField => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.adtTag adtName storageField) hOk + | adtField adtName variantName fieldName fieldIndex storageField => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.adtField adtName variantName fieldName fieldIndex + storageField) hOk + | mapping fieldName hKey => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.mapping fieldName hKey) hOk + | mappingWord fieldName hKey wordOffset => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.mappingWord fieldName hKey wordOffset) hOk + | mappingUint fieldName hKey => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.mappingUint fieldName hKey) hOk + | mapping2 fieldName hKey1 hKey2 => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.mapping2 fieldName hKey1 hKey2) hOk + | mapping2Word fieldName hKey1 hKey2 wordOffset => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.mapping2Word fieldName hKey1 hKey2 wordOffset) hOk + | structMember fieldName hKey memberName => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.structMember fieldName hKey memberName) hOk + | structMember2 fieldName hKey1 hKey2 memberName => + exact compileRequireFailCond_default_bridgedSource + (BridgedSourceExpr.structMember2 fieldName hKey1 hKey2 memberName) hOk | ge ha hb => simp only [compileRequireFailCond] at hOk obtain ⟨ca, cb, hA, hB, hEq⟩ := compileExpr_yulBinOp_ok hOk @@ -426,6 +1476,45 @@ theorem compileRequireFailCond_bridgedSource | localVar name => exact compileRequireFailCond_default_bridgedSource (.localVar name) (by simpa [compileRequireFailCond] using hOk) + | arrayLength name => + exact compileRequireFailCond_default_bridgedSource (.arrayLength name) + (by simpa [compileRequireFailCond] using hOk) + | caller => + exact compileRequireFailCond_default_bridgedSource .caller + (by simpa [compileRequireFailCond] using hOk) + | contractAddress => + exact compileRequireFailCond_default_bridgedSource .contractAddress + (by simpa [compileRequireFailCond] using hOk) + | msgValue => + exact compileRequireFailCond_default_bridgedSource .msgValue + (by simpa [compileRequireFailCond] using hOk) + | blockTimestamp => + exact compileRequireFailCond_default_bridgedSource .blockTimestamp + (by simpa [compileRequireFailCond] using hOk) + | blockNumber => + exact compileRequireFailCond_default_bridgedSource .blockNumber + (by simpa [compileRequireFailCond] using hOk) + | chainid => + exact compileRequireFailCond_default_bridgedSource .chainid + (by simpa [compileRequireFailCond] using hOk) + | blobbasefee => + exact compileRequireFailCond_default_bridgedSource .blobbasefee + (by simpa [compileRequireFailCond] using hOk) + | calldatasize => + exact compileRequireFailCond_default_bridgedSource .calldatasize + (by simpa [compileRequireFailCond] using hOk) + | calldataload hOffset => + exact compileRequireFailCond_default_bridgedSource (.calldataload hOffset) + (by simpa [compileRequireFailCond] using hOk) + | mload hOffset => + exact compileRequireFailCond_default_bridgedSource (.mload hOffset) + (by simpa [compileRequireFailCond] using hOk) + | tload hOffset => + exact compileRequireFailCond_default_bridgedSource (.tload hOffset) + (by simpa [compileRequireFailCond] using hOk) + | keccak256 hOffset hSize => + exact compileRequireFailCond_default_bridgedSource (.keccak256 hOffset hSize) + (by simpa [compileRequireFailCond] using hOk) | add ha hb => exact compileRequireFailCond_default_bridgedSource (.add ha hb) (by simpa [compileRequireFailCond] using hOk) @@ -456,6 +1545,9 @@ theorem compileRequireFailCond_bridgedSource | bitXor ha hb => exact compileRequireFailCond_default_bridgedSource (.bitXor ha hb) (by simpa [compileRequireFailCond] using hOk) + | bitNot ha => + exact compileRequireFailCond_default_bridgedSource (.bitNot ha) + (by simpa [compileRequireFailCond] using hOk) | shl hs hv => exact compileRequireFailCond_default_bridgedSource (.shl hs hv) (by simpa [compileRequireFailCond] using hOk) @@ -483,6 +1575,43 @@ theorem compileRequireFailCond_bridgedSource | slt ha hb => exact compileRequireFailCond_default_bridgedSource (.slt ha hb) (by simpa [compileRequireFailCond] using hOk) + | logicalAnd ha hb => + exact compileRequireFailCond_default_bridgedSource (.logicalAnd ha hb) + (by simpa [compileRequireFailCond] using hOk) + | logicalOr ha hb => + exact compileRequireFailCond_default_bridgedSource (.logicalOr ha hb) + (by simpa [compileRequireFailCond] using hOk) + | logicalNot ha => + exact compileRequireFailCond_default_bridgedSource (.logicalNot ha) + (by simpa [compileRequireFailCond] using hOk) + | ceilDiv ha hb => + exact compileRequireFailCond_default_bridgedSource (.ceilDiv ha hb) + (by simpa [compileRequireFailCond] using hOk) + | mulDivDown ha hb hc => + exact compileRequireFailCond_default_bridgedSource (.mulDivDown ha hb hc) + (by simpa [compileRequireFailCond] using hOk) + | mulDivUp ha hb hc => + exact compileRequireFailCond_default_bridgedSource (.mulDivUp ha hb hc) + (by simpa [compileRequireFailCond] using hOk) + | wMulDown ha hb => + exact compileRequireFailCond_default_bridgedSource (.wMulDown ha hb) + (by simpa [compileRequireFailCond] using hOk) + | wDivUp ha hb => + exact compileRequireFailCond_default_bridgedSource (.wDivUp ha hb) + (by simpa [compileRequireFailCond] using hOk) + | builtinExp hBase hExponent => + exact compileRequireFailCond_default_bridgedSource + (.builtinExp hBase hExponent) + (by simpa [compileRequireFailCond] using hOk) + | min ha hb => + exact compileRequireFailCond_default_bridgedSource (.min ha hb) + (by simpa [compileRequireFailCond] using hOk) + | max ha hb => + exact compileRequireFailCond_default_bridgedSource (.max ha hb) + (by simpa [compileRequireFailCond] using hOk) + | ite hCond hThen hElse => + exact compileRequireFailCond_default_bridgedSource (.ite hCond hThen hElse) + (by simpa [compileRequireFailCond] using hOk) /-- List-level closure: when every source expression in a list is `BridgedSourceExpr`, `compileExprList` produces a list whose every @@ -533,4 +1662,32 @@ theorem compileExprList_bridgedSource | inl h => subst h; exact hHeadBridged | inr h => exact hTailBridged yulExpr h +/-- Mapping-chain source-expression wrapper: when every key source expression + is in `BridgedSourceExpr`, the compiler's `mappingChain` read emits a + bridged `sload` over a `foldl mappingSlot` chain. + + Like the other mapping read closures, this stays at the abstract + `mappingSlot` helper boundary rather than claiming source-level + memory+keccak equivalence. -/ +theorem compileExpr_mappingChain_bridgedSource + (fields : List CompilationModel.Field) (src : DynamicDataSource) + {fieldName : String} {keys : List Expr} {out : YulExpr} + (hKeys : ∀ key ∈ keys, BridgedSourceExpr key) + (hOk : compileExpr fields src (.mappingChain fieldName keys) = .ok out) : + BridgedExpr out := by + simp only [compileExpr] at hOk + split at hOk + · simp at hOk + · split at hOk + · rename_i slot hFind + cases hCompiledKeys : compileExprList fields src keys with + | error err => + simp [bind, Except.bind, hCompiledKeys] at hOk + | ok keyExprs => + simp [bind, Except.bind, hCompiledKeys, Pure.pure, Except.pure] at hOk + subst out + exact bridgedExpr_sload_mappingSlotChain_lit slot keyExprs + (compileExprList_bridgedSource fields src hKeys hCompiledKeys) + · simp at hOk + end Compiler.Proofs.YulGeneration.Backends diff --git a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanStateBridge.lean b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanStateBridge.lean index 358702937..80f925ae6 100644 --- a/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanStateBridge.lean +++ b/Compiler/Proofs/YulGeneration/Backends/EvmYulLeanStateBridge.lean @@ -26,8 +26,7 @@ The bridge converts between word-level and byte-level representations. -/ -import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins -import Compiler.Proofs.YulGeneration.ReferenceOracle.State +import Compiler.Proofs.YulGeneration.RuntimeTypes import EvmYul.Yul.State import EvmYul.SharedState import EvmYul.State.Account @@ -535,6 +534,47 @@ private theorem calldataToByteArray_fold_get?_left omega _ = acc.get? i := byteArray_get?_append_left h +private theorem calldataToByteArray_fold_get?_word + (wordBytes : Nat → ByteArray) + (hWord : ∀ w, (wordBytes w).size = 32) + (hByte : + ∀ w i, i < 32 → + (wordBytes w).get? i = + some (UInt8.ofNat (w / 2^((31 - i) * 8) % 256))) : + ∀ (acc : ByteArray) (calldata : List Nat) (idx arg : Nat) + (rest : List Nat) (i : Nat), + calldata.drop idx = arg :: rest → + i < 32 → + (calldata.foldl (init := acc) fun acc w => acc ++ wordBytes w).get? + (acc.size + 32 * idx + i) = + some (UInt8.ofNat (arg / 2^((31 - i) * 8) % 256)) := by + intro acc calldata idx + induction idx generalizing acc calldata with + | zero => + intro arg rest i hdrop hi + simp only [List.drop_zero] at hdrop + subst calldata + simp only [List.foldl_cons] + rw [calldataToByteArray_fold_get?_left wordBytes hWord] + · rw [byteArray_get?_append_right] + · simpa using hByte arg i hi + · omega + · rw [ByteArray.size_append, hWord] + omega + · rw [ByteArray.size_append, hWord] + omega + | succ idx ih => + intro arg rest i hdrop hi + cases calldata with + | nil => + simp at hdrop + | cons head tail => + simp only [List.drop_succ_cons] at hdrop + simp only [List.foldl_cons] + have h := ih (acc ++ wordBytes head) tail arg rest i hdrop hi + simpa [ByteArray.size_append, hWord, Nat.mul_add, Nat.add_assoc, + Nat.add_comm, Nat.add_left_comm] using h + /-- The bridged calldata byte array has the same observable length as Verity's `calldatasize`: 4 selector bytes plus 32 bytes per calldata word. -/ theorem calldataToByteArray_size (selector : Nat) (calldata : List Nat) : @@ -671,23 +711,59 @@ theorem calldataToByteArray_arg0Byte have hWord : ∀ w, (wordBytes w).size = 32 := by intro w simp [wordBytes] - have hAccSize : (selectorBytes ++ wordBytes arg).size = 36 := by - rw [ByteArray.size_append] - simp [selectorBytes, wordBytes] - simp only [List.foldl_cons] - rw [calldataToByteArray_fold_get?_left wordBytes hWord] - · rw [byteArray_get?_append_right] - · unfold ByteArray.get? - split - · apply congrArg some - simp [ByteArray.get] - · rename_i hge - exact False.elim (hge (by simp; omega)) - · simp - · rw [hAccSize] - omega - · rw [hAccSize] - omega + have hByte : + ∀ w i, i < 32 → + (wordBytes w).get? i = + some (UInt8.ofNat (w / 2^((31 - i) * 8) % 256)) := by + intro w i hi + unfold ByteArray.get? + split + · apply congrArg some + simp [ByteArray.get, wordBytes] + · rename_i hnot + exact False.elim (hnot (by simp [wordBytes, hi])) + have h := + calldataToByteArray_fold_get?_word wordBytes hWord hByte selectorBytes + (arg :: rest) 0 arg rest i rfl hi + simpa [selectorBytes] using h + +/-- Byte-level projection for any aligned ABI argument word in bridged calldata. + If `calldata.drop idx = arg :: rest`, then byte `4 + 32*idx + i` is the + `i`th big-endian byte of `arg`. -/ +theorem calldataToByteArray_argByte_of_drop_eq_cons + (selector : Nat) (calldata : List Nat) (idx arg : Nat) (rest : List Nat) + (hdrop : calldata.drop idx = arg :: rest) (i : Nat) (hi : i < 32) : + (calldataToByteArray selector calldata).get? (4 + 32 * idx + i) = + some (UInt8.ofNat (arg / 2 ^ ((31 - i) * 8) % 256)) := by + unfold calldataToByteArray + let selectorBytes : ByteArray := + ByteArray.ofFn fun i : Fin 4 => + match i.1 with + | 0 => UInt8.ofNat (selector / 2^24 % 256) + | 1 => UInt8.ofNat (selector / 2^16 % 256) + | 2 => UInt8.ofNat (selector / 2^8 % 256) + | _ => UInt8.ofNat (selector % 256) + let wordBytes : Nat → ByteArray := fun w => + ByteArray.ofFn fun i : Fin 32 => + UInt8.ofNat (w / 2^((31 - i.1) * 8) % 256) + have hWord : ∀ w, (wordBytes w).size = 32 := by + intro w + simp [wordBytes] + have hByte : + ∀ w i, i < 32 → + (wordBytes w).get? i = + some (UInt8.ofNat (w / 2^((31 - i) * 8) % 256)) := by + intro w i hi + unfold ByteArray.get? + split + · apply congrArg some + simp [ByteArray.get, wordBytes] + · rename_i hnot + exact False.elim (hnot (by simp [wordBytes, hi])) + have h := + calldataToByteArray_fold_get?_word wordBytes hWord hByte selectorBytes + calldata idx arg rest i hdrop hi + simpa [selectorBytes] using h /-! ## Full State Conversion @@ -753,105 +829,6 @@ def extractStorage (sharedState : SharedState .Yul) (addr : AccountAddress) : | none => 0 | none => 0 -/-! ## Environment Field Bridge Proofs - -These theorems prove that Verity's `evalBuiltinCallWithContext` agrees with the -corresponding field extraction from the EVMYulLean state constructed by -`toSharedState`. Each theorem connects a stateful builtin's Verity semantics -to the state bridge. - -The proof pattern is uniform: -1. Unfold the Verity builtin to `some (field % evmModulus)` -2. Unfold the bridge to `natToUInt256 field` -3. Show `uint256ToNat (natToUInt256 field) = field % UInt256.size = field % evmModulus` - since `UInt256.size = evmModulus`. -/ - -/-- The `callvalue` builtin reads `msgValue` from Verity's state. - The state bridge stores `natToUInt256 state.msgValue` in `execEnv.weiValue`. - These agree modulo `evmModulus`. -/ -theorem callvalue_bridge (state : YulState) (observableSlots : List Nat) : - evalBuiltinCallWithContext state.storage state.sender state.msgValue - state.thisAddress state.blockTimestamp state.blockNumber state.chainId - state.blobBaseFee state.selector state.calldata "callvalue" [] = - some (uint256ToNat (toSharedState state observableSlots).executionEnv.weiValue) := by - simp [evalBuiltinCallWithContext, toSharedState, uint256ToNat, natToUInt256, - UInt256.toNat, UInt256.ofNat, Id.run, evmModulus, UInt256.size] - -/-- The `timestamp` builtin reads `blockTimestamp` from Verity's state. - The state bridge stores `state.blockTimestamp` in the block header's - `timestamp` field. EVMYulLean converts this to `UInt256.ofNat`. -/ -theorem timestamp_bridge (state : YulState) (observableSlots : List Nat) : - evalBuiltinCallWithContext state.storage state.sender state.msgValue - state.thisAddress state.blockTimestamp state.blockNumber state.chainId - state.blobBaseFee state.selector state.calldata "timestamp" [] = - some (uint256ToNat (UInt256.ofNat - (toSharedState state observableSlots).executionEnv.header.timestamp)) := by - simp [evalBuiltinCallWithContext, toSharedState, mkBlockHeader, uint256ToNat, - UInt256.toNat, UInt256.ofNat, Id.run, evmModulus, UInt256.size] - -/-- The `number` builtin reads `blockNumber` from Verity's state. - The state bridge stores `state.blockNumber` in the block header's - `number` field. EVMYulLean converts this to `UInt256.ofNat`. -/ -theorem number_bridge (state : YulState) (observableSlots : List Nat) : - evalBuiltinCallWithContext state.storage state.sender state.msgValue - state.thisAddress state.blockTimestamp state.blockNumber state.chainId - state.blobBaseFee state.selector state.calldata "number" [] = - some (uint256ToNat (UInt256.ofNat - (toSharedState state observableSlots).executionEnv.header.number)) := by - simp [evalBuiltinCallWithContext, toSharedState, mkBlockHeader, uint256ToNat, - UInt256.toNat, UInt256.ofNat, Id.run, evmModulus, UInt256.size] - -/-- The `calldatasize` builtin reads the size of the current calldata payload. - The state bridge encodes Verity calldata as 4 selector bytes followed by - one 32-byte word per calldata element. Both sides reduce the observable - length into the `UInt256` word domain, so the bridge agrees even when the - byte length wraps modulo `2^256`. -/ -theorem calldatasize_bridge (state : YulState) (observableSlots : List Nat) : - evalBuiltinCallWithContext state.storage state.sender state.msgValue - state.thisAddress state.blockTimestamp state.blockNumber state.chainId - state.blobBaseFee state.selector state.calldata "calldatasize" [] = - some (uint256ToNat (UInt256.ofNat - (toSharedState state observableSlots).executionEnv.calldata.size)) := by - simp [evalBuiltinCallWithContext, toSharedState, uint256ToNat, UInt256.toNat, - UInt256.ofNat, Id.run, UInt256.size, calldataToByteArray_size] - -set_option maxHeartbeats 8000000 in -/-- The `caller` builtin reads `sender` from Verity's state. - The state bridge stores `natToAddress state.sender` in `execEnv.source`. - EVMYulLean's CALLER extracts `source` as `UInt256.ofNat (Fin.val source)`. - - Since `natToAddress n = ⟨n % 2^160, _⟩`, the EVMYulLean side returns - `UInt256.ofNat (n % 2^160)`. Verity returns `sender` (no modular reduction - in `evalBuiltinCallWithContext`). Agreement requires the hypothesis that - `sender < evmModulus` (it's an Ethereum address, so `< 2^160 < 2^256`). -/ -theorem caller_bridge (state : YulState) (observableSlots : List Nat) - (hSender : state.sender < 2 ^ 160) : - evalBuiltinCallWithContext state.storage state.sender state.msgValue - state.thisAddress state.blockTimestamp state.blockNumber state.chainId - state.blobBaseFee state.selector state.calldata "caller" [] = - some (uint256ToNat (UInt256.ofNat - (toSharedState state observableSlots).executionEnv.source.val)) := by - simp [evalBuiltinCallWithContext, toSharedState, natToAddress, - uint256ToNat, UInt256.toNat, UInt256.ofNat, Id.run, UInt256.size] - omega - -set_option maxHeartbeats 8000000 in -/-- The `address` builtin reads `thisAddress` from Verity's state. - The state bridge stores `natToAddress state.thisAddress` in `execEnv.codeOwner`. - EVMYulLean's ADDRESS extracts `codeOwner` as `UInt256.ofNat (Fin.val codeOwner)`. - - Agreement requires `thisAddress < 2^160` (valid Ethereum address). -/ -theorem address_bridge (state : YulState) (observableSlots : List Nat) - (hAddr : state.thisAddress < 2 ^ 160) : - evalBuiltinCallWithContext state.storage state.sender state.msgValue - state.thisAddress state.blockTimestamp state.blockNumber state.chainId - state.blobBaseFee state.selector state.calldata "address" [] = - some (uint256ToNat (UInt256.ofNat - (toSharedState state observableSlots).executionEnv.codeOwner.val)) := by - simp [evalBuiltinCallWithContext, toSharedState, natToAddress, - uint256ToNat, UInt256.toNat, UInt256.ofNat, Id.run, evmModulus, UInt256.size] - omega - /-! ## Storage Bridge Proofs -/ /-- The derived `Ord` for `UInt256` generates diff --git a/Compiler/Proofs/YulGeneration/Codegen.lean b/Compiler/Proofs/YulGeneration/Codegen.lean index 2742bdf3d..69b69b7e0 100644 --- a/Compiler/Proofs/YulGeneration/Codegen.lean +++ b/Compiler/Proofs/YulGeneration/Codegen.lean @@ -1,7 +1,7 @@ import Compiler.Codegen import Compiler.Proofs.IRGeneration.IRInterpreter import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics -import Compiler.Proofs.YulGeneration.Lemmas +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanPureBuiltinLemmas namespace Compiler.Proofs.YulGeneration @@ -17,36 +17,65 @@ These lemmas capture the core obligations for Yul codegen correctness: -/ @[simp] -theorem emitYul_runtimeCode_eq (contract : IRContract) : +private theorem emitYul_runtimeCode_eq (contract : IRContract) : (Compiler.emitYul contract).runtimeCode = Compiler.runtimeCode contract := by rfl /-- Selector extraction via `selectorExpr` yields the 4-byte selector. -/ @[simp] -theorem evalYulExpr_selectorExpr (state : YulState) : +private theorem evalYulExpr_selectorExpr (state : YulState) : evalYulExpr state selectorExpr = some (state.selector % selectorModulus) := by - exact Compiler.Proofs.YulGeneration.evalYulExpr_selectorExpr_semantics state + have hShiftModEq : selectorShift % evmModulus = selectorShift := by + have hShiftLtModulus : selectorShift < evmModulus := by + norm_num [selectorShift, evmModulus] + exact Nat.mod_eq_of_lt hShiftLtModulus + have hSelectorShiftLt256 : selectorShift < 256 := by + norm_num [selectorShift] + have hSelectorShiftNotGe256 : ¬ 256 ≤ selectorShift := Nat.not_le_of_lt hSelectorShiftLt256 + have hSelectorWordLt : + (state.selector % selectorModulus) * 2 ^ selectorShift < evmModulus := by + have hModLt : state.selector % selectorModulus < selectorModulus := by + exact Nat.mod_lt _ (by decide) + have hPowPos : 0 < 2 ^ selectorShift := by + exact Nat.pow_pos (a := 2) (n := selectorShift) (by decide) + have hMulLt : + (state.selector % selectorModulus) * 2 ^ selectorShift < + selectorModulus * 2 ^ selectorShift := by + exact Nat.mul_lt_mul_of_pos_right hModLt hPowPos + have hModulusSplit : selectorModulus * 2 ^ selectorShift = evmModulus := by + norm_num [selectorModulus, selectorShift, evmModulus, Nat.pow_add, Nat.mul_comm, + Nat.mul_left_comm, Nat.mul_assoc] + simpa [hModulusSplit] using hMulLt + have hSelectorWordMod : + ((state.selector % selectorModulus) * 2 ^ selectorShift) % evmModulus = + (state.selector % selectorModulus) * 2 ^ selectorShift := by + exact Nat.mod_eq_of_lt hSelectorWordLt + simp [selectorExpr, evalYulExpr, evalYulCall, evalYulExprs, + evalBuiltinCallWithBackendContext, Backends.evalBuiltinCallWithEvmYulLeanContext, + Backends.evalBuiltinCallViaEvmYulLean, + calldataloadWord, selectorWord, + hShiftModEq, hSelectorWordMod, hSelectorShiftNotGe256] /-- Selector extraction yields the raw selector when it fits in 4 bytes. -/ @[simp] -theorem evalYulExpr_selectorExpr_eq (state : YulState) +private theorem evalYulExpr_selectorExpr_eq (state : YulState) (hselector : state.selector < selectorModulus) : evalYulExpr state selectorExpr = some state.selector := by simp [Nat.mod_eq_of_lt hselector] /-- Dispatch body emitted for one external function case. -/ -def switchCaseBody (fn : IRFunction) : List YulStmt := +private def switchCaseBody (fn : IRFunction) : List YulStmt := let valueGuard := if fn.payable then [] else [Compiler.callvalueGuard] [YulStmt.comment s!"{fn.name}()"] ++ valueGuard ++ [Compiler.calldatasizeGuard fn.params.length] ++ fn.body /-- Switch cases generated from IR functions. -/ -def switchCases (fns : List IRFunction) : List (Prod Nat (List YulStmt)) := +private def switchCases (fns : List IRFunction) : List (Prod Nat (List YulStmt)) := fns.map (fun f => (f.selector, switchCaseBody f)) /-- Default dispatch body used by `buildSwitch`. -/ -def switchDefaultCase +private def switchDefaultCase (fallback : Option IREntrypoint) (receive : Option IREntrypoint) : List YulStmt := match receive, fallback with @@ -76,43 +105,45 @@ def switchDefaultCase ]] /-- If the selector matches a case, the switch executes that case body (fueled). -/ -theorem execYulStmtFuel_switch_match +private theorem execYulStmtFuel_switch_match (state : YulState) (expr : YulExpr) (cases' : List (Prod Nat (List YulStmt))) (defaultCase : Option (List YulStmt)) (fuel v : Nat) (body : List YulStmt) (hEval : evalYulExpr state expr = some v) (hFind : List.find? (fun (c, _) => c = v) cases' = some (v, body)) : execYulStmtFuel (Nat.succ fuel) state (YulStmt.switch expr cases' defaultCase) = execYulStmtsFuel fuel state body := by - have hFind' : - List.find? (fun x : Prod Nat (List YulStmt) => decide (x.1 = v)) cases' = some (v, body) := by - simpa using hFind - simpa using (Compiler.Proofs.YulGeneration.execYulStmtFuel_switch_match_semantics - state expr cases' defaultCase fuel v body hEval hFind') + cases fuel with + | zero => + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind] + | succ fuel => + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind] /-- If no selector case matches, the switch executes the default (or continues). -/ -def execYulStmtFuel_switch_miss_result (state : YulState) (fuel : Nat) +private def execYulStmtFuel_switch_miss_result (state : YulState) (fuel : Nat) (defaultCase : Option (List YulStmt)) : YulExecResult := match defaultCase with | some body => execYulStmtsFuel fuel state body | none => YulExecResult.continue state -theorem execYulStmtFuel_switch_miss +private theorem execYulStmtFuel_switch_miss (state : YulState) (expr : YulExpr) (cases' : List (Prod Nat (List YulStmt))) (defaultCase : Option (List YulStmt)) (fuel v : Nat) (hEval : evalYulExpr state expr = some v) (hFind : List.find? (fun (c, _) => c = v) cases' = none) : execYulStmtFuel (Nat.succ fuel) state (YulStmt.switch expr cases' defaultCase) = execYulStmtFuel_switch_miss_result state fuel defaultCase := by - have hFind' : - List.find? (fun x : Prod Nat (List YulStmt) => decide (x.1 = v)) cases' = none := by - simpa using hFind - have h := - Compiler.Proofs.YulGeneration.execYulStmtFuel_switch_miss_semantics - state expr cases' defaultCase fuel v hEval hFind' - simpa [execYulStmtFuel_switch_miss_result] using h + cases fuel with + | zero => + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind, + execYulStmtFuel_switch_miss_result] + rfl + | succ fuel => + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind, + execYulStmtFuel_switch_miss_result] + rfl /- Bridge lemmas for switch-case lookup. -/ -theorem find_switch_case_of_find_function +private theorem find_switch_case_of_find_function (fns : List IRFunction) (sel : Nat) (fn : IRFunction) (hFind : fns.find? (fun f => f.selector == sel) = some fn) : (switchCases fns).find? (fun (c, _) => c = sel) = @@ -137,7 +168,7 @@ theorem find_switch_case_of_find_function /-- Selector-specialized variant: if `find?` hits `fn` at `sel`, the switch case lookup returns the same selector `sel` paired with `switchCaseBody fn`. -/ -theorem find_switch_case_of_find_function_eq_selector +private theorem find_switch_case_of_find_function_eq_selector (fns : List IRFunction) (sel : Nat) (fn : IRFunction) (hFind : fns.find? (fun f => f.selector == sel) = some fn) : (switchCases fns).find? (fun (c, _) => c = sel) = @@ -149,7 +180,7 @@ theorem find_switch_case_of_find_function_eq_selector exact h simpa [hSel] using hCase -theorem find_switch_case_of_find_function_none +private theorem find_switch_case_of_find_function_none (fns : List IRFunction) (sel : Nat) (hFind : fns.find? (fun f => f.selector == sel) = none) : (switchCases fns).find? (fun (c, _) => c = sel) = none := by @@ -175,30 +206,30 @@ theorem find_switch_case_of_find_function_none /-! ## Runtime code reduction lemmas -/ /-- Function definitions are no-ops in execution. -/ -@[simp] theorem execYulStmtFuel_funcDef (fuel : Nat) (state : YulState) +@[simp] private theorem execYulStmtFuel_funcDef (fuel : Nat) (state : YulState) (name : String) (params ret : List String) (body : List YulStmt) : execYulStmtFuel fuel state (YulStmt.funcDef name params ret body) = YulExecResult.continue state := by - cases fuel <;> simp [execYulStmtFuel, execYulFuel] + cases fuel <;> simp [execYulStmtFuel, legacyExecYulFuel] -/-- `execYulFuel` on a funcDef target gives `.continue state` for any fuel. -/ -@[simp] theorem execYulFuel_funcDef (fuel : Nat) (state : YulState) +/-- `legacyExecYulFuel` on a funcDef target gives `.continue state` for any fuel. -/ +@[simp] private theorem legacyExecYulFuel_funcDef (fuel : Nat) (state : YulState) (name : String) (params ret : List String) (body : List YulStmt) : - execYulFuel fuel state (.stmt (YulStmt.funcDef name params ret body)) = + legacyExecYulFuel fuel state (.stmt (YulStmt.funcDef name params ret body)) = YulExecResult.continue state := by - cases fuel <;> simp [execYulFuel] + cases fuel <;> simp [legacyExecYulFuel] /-- Stepping through a funcDef in a statement list consumes one fuel unit. -/ -@[simp] theorem execYulStmtsFuel_cons_funcDef (fuel : Nat) (state : YulState) +@[simp] private theorem execYulStmtsFuel_cons_funcDef (fuel : Nat) (state : YulState) (name : String) (params ret : List String) (body rest : List YulStmt) : execYulStmtsFuel (Nat.succ fuel) state (YulStmt.funcDef name params ret body :: rest) = execYulStmtsFuel fuel state rest := by - simp only [execYulStmtsFuel, execYulFuel] - rw [execYulFuel_funcDef] + simp only [execYulStmtsFuel, legacyExecYulFuel] + rw [legacyExecYulFuel_funcDef] /-- Executing funcDef statements followed by a suffix: the funcDefs are no-ops and each one burns one fuel unit. -/ -theorem execYulStmtsFuel_funcDefs_then_suffix (fuel : Nat) (state : YulState) +private theorem execYulStmtsFuel_funcDefs_then_suffix (fuel : Nat) (state : YulState) (prefix_ : List YulStmt) (suffix_ : List YulStmt) (hFuncDefs : ∀ s ∈ prefix_, ∃ nm p r b, s = YulStmt.funcDef nm p r b) : execYulStmtsFuel (prefix_.length + fuel) state (prefix_ ++ suffix_) = @@ -214,7 +245,7 @@ theorem execYulStmtsFuel_funcDefs_then_suffix (fuel : Nat) (state : YulState) exact ih state (fun s hs => hFuncDefs s (List.mem_cons_of_mem _ hs)) /-- Variant with `fuel ≥ prefix_.length` instead of exact `prefix_.length + fuel`. -/ -theorem execYulStmtsFuel_funcDefs_then_suffix_ge (fuel : Nat) (state : YulState) +private theorem execYulStmtsFuel_funcDefs_then_suffix_ge (fuel : Nat) (state : YulState) (prefix_ : List YulStmt) (suffix_ : List YulStmt) (hFuncDefs : ∀ s ∈ prefix_, ∃ nm p r b, s = YulStmt.funcDef nm p r b) (hFuel : fuel ≥ prefix_.length) : diff --git a/Compiler/Proofs/YulGeneration/Equivalence.lean b/Compiler/Proofs/YulGeneration/Equivalence.lean index 94139ce98..61b9ef978 100644 --- a/Compiler/Proofs/YulGeneration/Equivalence.lean +++ b/Compiler/Proofs/YulGeneration/Equivalence.lean @@ -1,5 +1,6 @@ import Compiler.Codegen import Compiler.Proofs.IRGeneration.IRInterpreter +import Compiler.Proofs.YulGeneration.IRFuel import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics namespace Compiler.Proofs.YulGeneration @@ -10,7 +11,7 @@ open Compiler.Yul /-! ## IR ↔ Yul State Alignment -/ -def yulStateOfIR (_selector : Nat) (state : IRState) : YulState := +private def yulStateOfIR (_selector : Nat) (state : IRState) : YulState := { vars := state.vars storage := state.storage transientStorage := state.transientStorage @@ -27,40 +28,17 @@ def yulStateOfIR (_selector : Nat) (state : IRState) : YulState := blobBaseFee := state.blobBaseFee events := state.events } -def statesAligned (selector : Nat) (ir : IRState) (yul : YulState) : Prop := +private def statesAligned (selector : Nat) (ir : IRState) (yul : YulState) : Prop := yul = yulStateOfIR selector ir -/-! ## Bridging IR and Yul Semantics - -These helpers wire IR-level execution to Yul runtime execution so we can -compare results directly in smoke tests. --/ - -noncomputable def interpretYulFromIR (contract : IRContract) (tx : IRTransaction) (state : IRState) : YulResult := - interpretYulRuntime (Compiler.emitYul contract).runtimeCode (YulTransaction.ofIR tx) state.storage state.events - -/-- Interpret just a function body as Yul runtime code. -/ -noncomputable def interpretYulBody (fn : IRFunction) (tx : IRTransaction) (state : IRState) : YulResult := - interpretYulRuntime fn.body (YulTransaction.ofIR tx) state.storage state.events - -/-- Interpret a function body starting from an aligned IR-derived state. -/ -def resultsMatchOn (slots : List Nat) (mappingKeys : List (Nat × Nat)) - (ir : IRResult) (yul : YulResult) : Bool := - ir.success == yul.success && - ir.returnValue == yul.returnValue && - slots.all (fun slot => - ir.finalStorage (IRStorageSlot.ofNat slot) == yul.finalStorage (IRStorageSlot.ofNat slot)) && - mappingKeys.all (fun (base, key) => ir.finalMappings base key == yul.finalMappings base key) && - ir.events == yul.events - -/-! ## Layer 3 Equivalence Scaffolding +/- ## Layer 3 Equivalence Scaffolding These statements capture the generic proof shape for IR → Yul equivalence. They are intentionally parameterized so contract-level results become mechanical instantiations once the instruction-level lemmas are proven. -/ -def execResultsAligned (selector : Nat) : IRExecResult → YulExecResult → Prop +private def execResultsAligned (selector : Nat) : IRExecResult → YulExecResult → Prop | .continue ir, .continue yul => statesAligned selector ir yul | .return v ir, .return v' yul => v = v' ∧ statesAligned selector ir yul | .stop ir, .stop yul => statesAligned selector ir yul @@ -68,40 +46,14 @@ def execResultsAligned (selector : Nat) : IRExecResult → YulExecResult → Pro | _, _ => False /-- Results match when success, return value, and storage/mapping functions agree. -/ -def resultsMatch (ir : IRResult) (yul : YulResult) : Prop := +private def resultsMatch (ir : IRResult) (yul : YulResult) : Prop := ir.success = yul.success ∧ ir.returnValue = yul.returnValue ∧ (∀ slot, ir.finalStorage slot = yul.finalStorage slot) ∧ (∀ base key, ir.finalMappings base key = yul.finalMappings base key) ∧ ir.events = yul.events -def irResultOfExecWithRollback (rollback : IRState) : IRExecResult → IRResult - | .continue s => - { success := true - returnValue := s.returnValue - finalStorage := s.storage - finalMappings := Compiler.Proofs.storageAsMappings s.storage - events := s.events } - | .return v s => - { success := true - returnValue := some v - finalStorage := s.storage - finalMappings := Compiler.Proofs.storageAsMappings s.storage - events := s.events } - | .stop s => - { success := true - returnValue := none - finalStorage := s.storage - finalMappings := Compiler.Proofs.storageAsMappings s.storage - events := s.events } - | .revert _ => - { success := false - returnValue := none - finalStorage := rollback.storage - finalMappings := Compiler.Proofs.storageAsMappings rollback.storage - events := rollback.events } - -def yulResultOfExecWithRollback (rollback : YulState) : YulExecResult → YulResult +private def irResultOfExecWithRollback (rollback : IRState) : IRExecResult → IRResult | .continue s => { success := true returnValue := s.returnValue @@ -128,13 +80,13 @@ def yulResultOfExecWithRollback (rollback : YulState) : YulExecResult → YulRes events := rollback.events } /-- Interpret a function body starting from an aligned IR-derived state. -/ -noncomputable def interpretYulBodyFromState +private noncomputable def interpretYulBodyFromState (fn : IRFunction) (selector : Nat) (state rollback : IRState) : YulResult := let yulState := yulStateOfIR selector state let yulRollback := yulStateOfIR selector rollback yulResultOfExecWithRollback yulRollback (execYulStmts yulState fn.body) -theorem resultsMatch_of_execResultsAligned +private theorem resultsMatch_of_execResultsAligned (selector : Nat) (rollbackIR : IRState) (rollbackYul : YulState) (hAligned : statesAligned selector rollbackIR rollbackYul) : ∀ irExec yulExec, @@ -193,7 +145,7 @@ bodies. They do not assume any specific instruction equivalence proof; instead, they require it as a parameter and then compose it. -/ -theorem statesAligned_refl (selector : Nat) (state : IRState) : +private theorem statesAligned_refl (selector : Nat) (state : IRState) : statesAligned selector state (yulStateOfIR selector state) := by rfl @@ -204,11 +156,11 @@ fuel before executing the first statement. They are intended as building blocks for the generic sequence equivalence proof. -/ -theorem execYulStmtsFuel_nil (fuel : Nat) (state : YulState) : +private theorem execYulStmtsFuel_nil (fuel : Nat) (state : YulState) : execYulStmtsFuel fuel state [] = .continue state := by cases fuel <;> rfl -theorem execYulStmtsFuel_cons +private theorem execYulStmtsFuel_cons (fuel : Nat) (state : YulState) (stmt : YulStmt) (rest : List YulStmt) : execYulStmtsFuel (Nat.succ fuel) state (stmt :: rest) = match execYulStmtFuel fuel state stmt with @@ -218,7 +170,7 @@ theorem execYulStmtsFuel_cons | .revert s => .revert s := by rfl -theorem execYulStmtFuel_for +private theorem execYulStmtFuel_for (fuel : Nat) (state : YulState) (init : List YulStmt) (cond : YulExpr) (post body : List YulStmt) : execYulStmtFuel (Nat.succ fuel) state (YulStmt.for_ init cond post body) = match execYulStmtsFuel fuel state init with @@ -237,23 +189,14 @@ theorem execYulStmtFuel_for | other => other := by rfl -/-! ## Fuel-Parametric Aliases - -`execIRStmtFuel`/`execIRStmtsFuel` are aliases for the total IR executors -in IRInterpreter.lean. Downstream proofs use these names. --/ - -abbrev execIRStmtFuel := @execIRStmt -abbrev execIRStmtsFuel := @execIRStmts - /-- Instruction-level equivalence goal: single IR statement matches Yul statement (fuel-parametric). -/ -def execIRStmt_equiv_execYulStmt_goal +private def execIRStmt_equiv_execYulStmt_goal (selector : Nat) (fuel : Nat) (stmt : YulStmt) (irState : IRState) (yulState : YulState) : Prop := statesAligned selector irState yulState → execResultsAligned selector (execIRStmtFuel fuel irState stmt) (execYulStmtFuel fuel yulState stmt) /-- Sequence/program equivalence goal: statement lists compose under alignment (fuel-parametric). -/ -def execIRStmts_equiv_execYulStmts_goal +private def execIRStmts_equiv_execYulStmts_goal (selector : Nat) (fuel : Nat) (stmts : List YulStmt) (irState : IRState) (yulState : YulState) : Prop := statesAligned selector irState yulState → execResultsAligned selector (execIRStmtsFuel fuel irState stmts) (execYulStmtsFuel fuel yulState stmts) @@ -270,53 +213,7 @@ private theorem stmt_align_contra apply hImpossible simpa [hIR, hYul] using hStmt -theorem execIRStmtsFuel_nil (fuel : Nat) (state : IRState) : - execIRStmtsFuel fuel state [] = .continue state := by - simp [execIRStmtsFuel, execIRStmts] - -theorem execIRStmtsFuel_cons - (fuel : Nat) (state : IRState) (stmt : YulStmt) (rest : List YulStmt) : - execIRStmtsFuel (Nat.succ fuel) state (stmt :: rest) = - match execIRStmtFuel fuel state stmt with - | .continue s' => execIRStmtsFuel fuel s' rest - | .return v s => .return v s - | .stop s => .stop s - | .revert s => .revert s := by - -- The mutual definition unfolds directly - rfl - -def execIRFunctionFuel (fuel : Nat) (fn : IRFunction) (args : List Nat) (initialState : IRState) : - IRResult := - let stateWithParams := fn.params.zip args |>.foldl - (fun s (p, v) => s.setVar p.name v) - initialState - match execIRStmtsFuel fuel stateWithParams fn.body with - | .continue s => - { success := true - returnValue := s.returnValue - finalStorage := s.storage - finalMappings := Compiler.Proofs.storageAsMappings s.storage - events := s.events } - | .return v s => - { success := true - returnValue := some v - finalStorage := s.storage - finalMappings := Compiler.Proofs.storageAsMappings s.storage - events := s.events } - | .stop s => - { success := true - returnValue := none - finalStorage := s.storage - finalMappings := Compiler.Proofs.storageAsMappings s.storage - events := s.events } - | .revert _ => - { success := false - returnValue := none - finalStorage := initialState.storage - finalMappings := Compiler.Proofs.storageAsMappings initialState.storage - events := initialState.events } - -def ir_yul_function_equiv_fuel_goal +private def ir_yul_function_equiv_fuel_goal (fn : IRFunction) (selector : Nat) (args : List Nat) (initialState : IRState) : Prop := resultsMatch (execIRFunctionFuel (sizeOf fn.body + 1) fn args initialState) @@ -335,7 +232,7 @@ later proofs can specialize to the compiler-chosen fuel without re-proving the composition logic. -/ -theorem execIRStmtsFuel_equiv_execYulStmtsFuel_of_stmt_equiv +private theorem execIRStmtsFuel_equiv_execYulStmtsFuel_of_stmt_equiv (stmt_equiv : ∀ selector fuel stmt irState yulState, execIRStmt_equiv_execYulStmt_goal selector fuel stmt irState yulState) : @@ -353,7 +250,7 @@ theorem execIRStmtsFuel_equiv_execYulStmtsFuel_of_stmt_equiv cases fuel with | zero => simp [execIRStmtsFuel, execIRStmts, - execYulStmtsFuel, execYulFuel, execResultsAligned, hAligned] + execYulStmtsFuel, legacyExecYulFuel, execResultsAligned, hAligned] | succ fuel => have hStmt := stmt_equiv selector fuel stmt irState yulState hAligned cases hIR : execIRStmtFuel fuel irState stmt with @@ -401,7 +298,7 @@ theorem execIRStmtsFuel_equiv_execYulStmtsFuel_of_stmt_equiv | «stop» y' => exact False.elim (stmt_align_contra (hStmt := hStmt) (hIR := hIR) (hYul := hYul) (by simp [execResultsAligned])) -theorem execIRStmtsFuel_equiv_execYulStmts_of_stmt_equiv +private theorem execIRStmtsFuel_equiv_execYulStmts_of_stmt_equiv (stmt_equiv : ∀ selector fuel stmt irState yulState, execIRStmt_equiv_execYulStmt_goal selector fuel stmt irState yulState) : @@ -416,7 +313,7 @@ theorem execIRStmtsFuel_equiv_execYulStmts_of_stmt_equiv selector (sizeOf stmts + 1) stmts irState yulState hAligned simpa [execYulStmts] using hFuel -theorem execIRFunctionFuel_equiv_interpretYulBodyFromState_of_stmt_equiv +private theorem execIRFunctionFuel_equiv_interpretYulBodyFromState_of_stmt_equiv (stmt_equiv : ∀ selector fuel stmt irState yulState, execIRStmt_equiv_execYulStmt_goal selector fuel stmt irState yulState) : @@ -444,7 +341,7 @@ theorem execIRFunctionFuel_equiv_interpretYulBodyFromState_of_stmt_equiv (resultsMatch_of_execResultsAligned selector initialState (yulStateOfIR selector initialState) hRollback _ _ hExec) -theorem ir_yul_function_equiv_fuel_goal_of_stmt_equiv +private theorem ir_yul_function_equiv_fuel_goal_of_stmt_equiv (stmt_equiv : ∀ selector fuel stmt irState yulState, execIRStmt_equiv_execYulStmt_goal selector fuel stmt irState yulState) : @@ -455,25 +352,7 @@ theorem ir_yul_function_equiv_fuel_goal_of_stmt_equiv (execIRFunctionFuel_equiv_interpretYulBodyFromState_of_stmt_equiv stmt_equiv selector fn args initialState) -/-! ## Fuel Adequacy - -The IR executors are total (fuel-parametric) and the fuel aliases -resolve by `rfl`. No axiom needed. --/ - -def execIRFunctionFuel_adequate_goal - (fn : IRFunction) (args : List Nat) (initialState : IRState) : Prop := - execIRFunctionFuel (sizeOf fn.body + 1) fn args initialState = - execIRFunction fn args initialState - -/-- Fuel adequacy holds by `rfl` (fuel aliases resolve to total executors). -/ -theorem execIRFunctionFuel_adequate - (fn : IRFunction) (args : List Nat) (initialState : IRState) : - execIRFunctionFuel_adequate_goal fn args initialState := by - unfold execIRFunctionFuel_adequate_goal execIRFunctionFuel execIRFunction execIRStmtsFuel - rfl - -theorem ir_yul_function_equiv_from_state_of_fuel_goal +private theorem ir_yul_function_equiv_from_state_of_fuel_goal (fn : IRFunction) (selector : Nat) (args : List Nat) (initialState : IRState) (hFuel : execIRFunctionFuel (sizeOf fn.body + 1) fn args initialState = @@ -488,7 +367,7 @@ theorem ir_yul_function_equiv_from_state_of_fuel_goal initialState) := by simpa [ir_yul_function_equiv_fuel_goal, hFuel] using hFuelGoal -theorem ir_yul_function_equiv_from_state_of_fuel_goal_and_adequacy +private theorem ir_yul_function_equiv_from_state_of_fuel_goal_and_adequacy (fn : IRFunction) (selector : Nat) (args : List Nat) (initialState : IRState) (hAdequacy : execIRFunctionFuel_adequate_goal fn args initialState) (hFuelGoal : ir_yul_function_equiv_fuel_goal fn selector args initialState) : @@ -503,7 +382,7 @@ theorem ir_yul_function_equiv_from_state_of_fuel_goal_and_adequacy · simpa [execIRFunctionFuel_adequate_goal] using hAdequacy · exact hFuelGoal -theorem ir_yul_function_equiv_from_state_of_stmt_equiv_and_adequacy +private theorem ir_yul_function_equiv_from_state_of_stmt_equiv_and_adequacy (stmt_equiv : ∀ selector fuel stmt irState yulState, execIRStmt_equiv_execYulStmt_goal selector fuel stmt irState yulState) @@ -529,7 +408,7 @@ Since `execIRFunctionFuel` and `execIRFunction` are definitionally equal (fuel adequacy is `rfl`), the adequacy hypothesis is always trivially dischargeable. This theorem composes `stmt_equiv` with the internal adequacy proof, eliminating the need for callers to supply it. -/ -theorem ir_yul_function_equiv_from_state_of_stmt_equiv +private theorem ir_yul_function_equiv_from_state_of_stmt_equiv (stmt_equiv : ∀ selector fuel stmt irState yulState, execIRStmt_equiv_execYulStmt_goal selector fuel stmt irState yulState) diff --git a/Compiler/Proofs/YulGeneration/IRFuel.lean b/Compiler/Proofs/YulGeneration/IRFuel.lean new file mode 100644 index 000000000..ae8dea48e --- /dev/null +++ b/Compiler/Proofs/YulGeneration/IRFuel.lean @@ -0,0 +1,82 @@ +import Compiler.Proofs.IRGeneration.IRInterpreter + +namespace Compiler.Proofs.YulGeneration + +open Compiler +open Compiler.Proofs.IRGeneration +open Compiler.Yul + +/-! ## Fuel-Parametric IR Aliases + +These names are shared by the source-to-IR proof stack and the legacy IR/Yul +equivalence stack. They are intentionally kept free of the reference-oracle Yul +interpreter so IR-generation compiler-correctness modules do not need to import +`Compiler.Proofs.YulGeneration.Equivalence` just to talk about fuel-indexed IR +execution. +-/ + +abbrev execIRStmtFuel := @execIRStmt +abbrev execIRStmtsFuel := @execIRStmts + +theorem execIRStmtsFuel_nil (fuel : Nat) (state : IRState) : + execIRStmtsFuel fuel state [] = .continue state := by + simp [execIRStmtsFuel, execIRStmts] + +theorem execIRStmtsFuel_cons + (fuel : Nat) (state : IRState) (stmt : YulStmt) (rest : List YulStmt) : + execIRStmtsFuel (Nat.succ fuel) state (stmt :: rest) = + match execIRStmtFuel fuel state stmt with + | .continue s' => execIRStmtsFuel fuel s' rest + | .return v s => .return v s + | .stop s => .stop s + | .revert s => .revert s := by + rfl + +def execIRFunctionFuel + (fuel : Nat) (fn : IRFunction) (args : List Nat) + (initialState : IRState) : + IRResult := + let stateWithParams := fn.params.zip args |>.foldl + (fun s (p, v) => s.setVar p.name v) + initialState + match execIRStmtsFuel fuel stateWithParams fn.body with + | .continue s => + { success := true + returnValue := s.returnValue + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } + | .return v s => + { success := true + returnValue := some v + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } + | .stop s => + { success := true + returnValue := none + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } + | .revert _ => + { success := false + returnValue := none + finalStorage := initialState.storage + finalMappings := Compiler.Proofs.storageAsMappings initialState.storage + events := initialState.events } + +def execIRFunctionFuel_adequate_goal + (fn : IRFunction) (args : List Nat) (initialState : IRState) : Prop := + execIRFunctionFuel (sizeOf fn.body + 1) fn args initialState = + execIRFunction fn args initialState + +/-- Fuel adequacy holds by `rfl` because the fuel aliases resolve to the total +IR executors. -/ +theorem execIRFunctionFuel_adequate + (fn : IRFunction) (args : List Nat) (initialState : IRState) : + execIRFunctionFuel_adequate_goal fn args initialState := by + unfold execIRFunctionFuel_adequate_goal execIRFunctionFuel execIRFunction + execIRStmtsFuel + rfl + +end Compiler.Proofs.YulGeneration diff --git a/Compiler/Proofs/YulGeneration/Lemmas.lean b/Compiler/Proofs/YulGeneration/Lemmas.lean index 6b8b07194..034687017 100644 --- a/Compiler/Proofs/YulGeneration/Lemmas.lean +++ b/Compiler/Proofs/YulGeneration/Lemmas.lean @@ -1,5 +1,6 @@ import Compiler.Codegen import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanPureBuiltinLemmas namespace Compiler.Proofs.YulGeneration @@ -12,7 +13,7 @@ These lemmas connect the runtime codegen structure with the Yul semantics. -/ set_option maxHeartbeats 1000000 in -@[simp] theorem evalYulExpr_selectorExpr_semantics : +@[simp] private theorem evalYulExpr_selectorExpr_semantics : ∀ state : YulState, evalYulExpr state selectorExpr = some (state.selector % selectorModulus) := by intro state have hShiftModEq : selectorShift % evmModulus = selectorShift := by @@ -41,11 +42,13 @@ set_option maxHeartbeats 1000000 in (state.selector % selectorModulus) * 2 ^ selectorShift := by exact Nat.mod_eq_of_lt hSelectorWordLt simp [selectorExpr, evalYulExpr, evalYulCall, evalYulExprs, - evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext, calldataloadWord, selectorWord, + evalBuiltinCallWithBackendContext, Backends.evalBuiltinCallWithEvmYulLeanContext, + Backends.evalBuiltinCallViaEvmYulLean, + calldataloadWord, selectorWord, hShiftModEq, hSelectorWordMod, hSelectorShiftNotGe256] @[simp] -theorem execYulStmtFuel_switch_match_semantics +private theorem execYulStmtFuel_switch_match_semantics (state : YulState) (expr : YulExpr) (cases' : List (Nat × List YulStmt)) (defaultCase : Option (List YulStmt)) (fuel v : Nat) (body : List YulStmt) (hEval : evalYulExpr state expr = some v) @@ -54,12 +57,12 @@ theorem execYulStmtFuel_switch_match_semantics execYulStmtsFuel fuel state body := by cases fuel with | zero => - simp [execYulStmtFuel, execYulStmtsFuel, execYulFuel, hEval, hFind] + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind] | succ fuel => - simp [execYulStmtFuel, execYulStmtsFuel, execYulFuel, hEval, hFind] + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind] @[simp] -theorem execYulStmtFuel_switch_miss_semantics +private theorem execYulStmtFuel_switch_miss_semantics (state : YulState) (expr : YulExpr) (cases' : List (Nat × List YulStmt)) (defaultCase : Option (List YulStmt)) (fuel v : Nat) (hEval : evalYulExpr state expr = some v) @@ -70,10 +73,10 @@ theorem execYulStmtFuel_switch_miss_semantics | none => YulExecResult.continue state) := by cases fuel with | zero => - simp [execYulStmtFuel, execYulStmtsFuel, execYulFuel, hEval, hFind] + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind] rfl | succ fuel => - simp [execYulStmtFuel, execYulStmtsFuel, execYulFuel, hEval, hFind] + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind] rfl end Compiler.Proofs.YulGeneration diff --git a/Compiler/Proofs/YulGeneration/LogNames.lean b/Compiler/Proofs/YulGeneration/LogNames.lean new file mode 100644 index 000000000..8aa49b642 --- /dev/null +++ b/Compiler/Proofs/YulGeneration/LogNames.lean @@ -0,0 +1,8 @@ +namespace Compiler.Proofs.YulGeneration + +/-- Yul log builtin names accepted by the proof-side runtime models. -/ +def isYulLogName (func : String) : Bool := + func == "log0" || func == "log1" || func == "log2" || + func == "log3" || func == "log4" + +end Compiler.Proofs.YulGeneration diff --git a/Compiler/Proofs/YulGeneration/Preservation.lean b/Compiler/Proofs/YulGeneration/Preservation.lean index 4984246bc..e2b18db5a 100644 --- a/Compiler/Proofs/YulGeneration/Preservation.lean +++ b/Compiler/Proofs/YulGeneration/Preservation.lean @@ -1,6 +1,7 @@ -import Compiler.Proofs.YulGeneration.Codegen -import Compiler.Proofs.YulGeneration.Equivalence -import Compiler.Proofs.YulGeneration.StatementEquivalence +import Compiler.Codegen +import Compiler.Proofs.YulGeneration.RuntimeTypes +import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanPureBuiltinLemmas import Compiler.Proofs.IRGeneration.IRInterpreter set_option linter.unusedSimpArgs false @@ -21,6 +22,15 @@ executing an IR function body matches executing the same Yul statements. See `TRUST_ASSUMPTIONS.md` for the full trust-boundary description. -/ +private noncomputable def interpretYulFromIR + (contract : IRContract) (tx : IRTransaction) (state : IRState) : YulResult := + interpretYulRuntime (Compiler.emitYul contract).runtimeCode + (YulTransaction.ofIR tx) state.storage state.events + +private noncomputable def interpretYulBody + (fn : IRFunction) (tx : IRTransaction) (state : IRState) : YulResult := + interpretYulRuntime fn.body (YulTransaction.ofIR tx) state.storage state.events + @[simp] private theorem interpretYulBody_eq_runtime (fn : IRFunction) (tx : IRTransaction) (state : IRState) : interpretYulBody fn tx state = interpretYulRuntime fn.body (YulTransaction.ofIR tx) state.storage state.events := by @@ -45,20 +55,20 @@ See `TRUST_ASSUMPTIONS.md` for the full trust-boundary description. simp [interpretYulBody] mutual -def yulExprNoRef (name : String) : YulExpr → Prop +private def yulExprNoRef (name : String) : YulExpr → Prop | .lit _ => True | .hex _ => True | .str _ => True | .ident ident => ident ≠ name | .call _ args => yulExprsNoRef name args -def yulExprsNoRef (name : String) : List YulExpr → Prop +private def yulExprsNoRef (name : String) : List YulExpr → Prop | [] => True | expr :: exprs => yulExprNoRef name expr ∧ yulExprsNoRef name exprs end mutual -def yulStmtNoRef (name : String) : YulStmt → Prop +private def yulStmtNoRef (name : String) : YulStmt → Prop | .comment _ => True | .let_ _ value => yulExprNoRef name value | .letMany _ value => yulExprNoRef name value @@ -75,48 +85,21 @@ def yulStmtNoRef (name : String) : YulStmt → Prop | .block stmts => yulStmtsNoRef name stmts | .funcDef _ _ _ _ => True -def yulStmtsNoRef (name : String) : List YulStmt → Prop +private def yulStmtsNoRef (name : String) : List YulStmt → Prop | [] => True | stmt :: stmts => yulStmtNoRef name stmt ∧ yulStmtsNoRef name stmts -def yulSwitchCasesNoRef (name : String) : List (Nat × List YulStmt) → Prop +private def yulSwitchCasesNoRef (name : String) : List (Nat × List YulStmt) → Prop | [] => True | (_, body) :: rest => yulStmtsNoRef name body ∧ yulSwitchCasesNoRef name rest -def yulOptionStmtsNoRef (name : String) : Option (List YulStmt) → Prop +private def yulOptionStmtsNoRef (name : String) : Option (List YulStmt) → Prop | none => True | some body => yulStmtsNoRef name body end -/-! ### Loop-free syntactic predicates - -Decidable predicates checking that a Yul AST does not contain `for_` loops. -These are `Bool`-valued so the compiler can discharge them automatically via `rfl`. -/ -mutual -def yulStmtLoopFree : YulStmt → Bool - | .comment _ | .let_ _ _ | .letMany _ _ | .assign _ _ | .expr _ | .leave => true - | .if_ _ body => yulStmtsLoopFree body - | .for_ _ _ _ _ => false - | .switch _ cases defaultCase => - yulSwitchCasesLoopFree cases && yulOptionStmtsLoopFree defaultCase - | .block stmts => yulStmtsLoopFree stmts - | .funcDef _ _ _ body => yulStmtsLoopFree body - -def yulStmtsLoopFree : List YulStmt → Bool - | [] => true - | stmt :: stmts => yulStmtLoopFree stmt && yulStmtsLoopFree stmts - -def yulSwitchCasesLoopFree : List (Nat × List YulStmt) → Bool - | [] => true - | (_, body) :: rest => yulStmtsLoopFree body && yulSwitchCasesLoopFree rest - -def yulOptionStmtsLoopFree : Option (List YulStmt) → Bool - | none => true - | some body => yulStmtsLoopFree body -end - /-- Explicit theorem hypothesis used in place of the old kernel axiom. -/ -def HasSelectorDeadBridge (body : List YulStmt) : Prop := +private def HasSelectorDeadBridge (body : List YulStmt) : Prop := ∀ state fuel, yulStmtsNoRef "__has_selector" body → yulResultOfExecWithRollback state @@ -128,21 +111,244 @@ def HasSelectorDeadBridge (body : List YulStmt) : Prop := private def initialYulState (tx : YulTransaction) (state : IRState) : YulState := YulState.initial tx state.storage state.events -/-- Preconditions under which the generated dispatch guards behave like the - intended source-level checks for a selected function case. -/ -def DispatchGuardsSafe (fn : IRFunction) (tx : IRTransaction) : Prop := - (fn.payable = true ∨ tx.msgValue % evmModulus = 0) ∧ - 4 + fn.params.length * 32 < evmModulus +private def resultsMatch (ir : IRResult) (yul : YulResult) : Prop := + ir.success = yul.success ∧ + ir.returnValue = yul.returnValue ∧ + (∀ slot, ir.finalStorage slot = yul.finalStorage slot) ∧ + (∀ base key, ir.finalMappings base key = yul.finalMappings base key) ∧ + ir.events = yul.events + +private def switchCaseBody (fn : IRFunction) : List YulStmt := + let valueGuard := if fn.payable then [] else [Compiler.callvalueGuard] + [YulStmt.comment s!"{fn.name}()"] ++ valueGuard ++ + [Compiler.calldatasizeGuard fn.params.length] ++ fn.body + +private def switchCases (fns : List IRFunction) : List (Prod Nat (List YulStmt)) := + fns.map (fun f => (f.selector, switchCaseBody f)) + +private def switchDefaultCase + (fallback : Option IREntrypoint) + (receive : Option IREntrypoint) : List YulStmt := + match receive, fallback with + | none, none => + [YulStmt.expr (YulExpr.call "revert" [YulExpr.lit 0, YulExpr.lit 0])] + | none, some fb => + let valueGuard := if fb.payable then [] else [Compiler.callvalueGuard] + [YulStmt.comment "fallback()"] ++ valueGuard ++ fb.body + | some rc, none => + let receiveGuard := if rc.payable then [] else [Compiler.callvalueGuard] + [YulStmt.block [ + YulStmt.let_ "__is_empty_calldata" + (YulExpr.call "eq" [YulExpr.call "calldatasize" [], YulExpr.lit 0]), + YulStmt.if_ (YulExpr.ident "__is_empty_calldata") + ([YulStmt.comment "receive()"] ++ receiveGuard ++ rc.body), + YulStmt.if_ (YulExpr.call "iszero" [YulExpr.ident "__is_empty_calldata"]) + [YulStmt.expr (YulExpr.call "revert" [YulExpr.lit 0, YulExpr.lit 0])] + ]] + | some rc, some fb => + let receiveGuard := if rc.payable then [] else [Compiler.callvalueGuard] + let fallbackGuard := if fb.payable then [] else [Compiler.callvalueGuard] + [YulStmt.block [ + YulStmt.let_ "__is_empty_calldata" + (YulExpr.call "eq" [YulExpr.call "calldatasize" [], YulExpr.lit 0]), + YulStmt.if_ (YulExpr.ident "__is_empty_calldata") + ([YulStmt.comment "receive()"] ++ receiveGuard ++ rc.body), + YulStmt.if_ (YulExpr.call "iszero" [YulExpr.ident "__is_empty_calldata"]) + ([YulStmt.comment "fallback()"] ++ fallbackGuard ++ fb.body) + ]] + +@[simp] +private theorem preservation_execYulStmtFuel_funcDef (fuel : Nat) (state : YulState) + (name : String) (params ret : List String) (body : List YulStmt) : + execYulStmtFuel fuel state (YulStmt.funcDef name params ret body) = + YulExecResult.continue state := by + cases fuel <;> simp [execYulStmtFuel, legacyExecYulFuel] + +@[simp] +private theorem preservation_legacyExecYulFuel_funcDef (fuel : Nat) (state : YulState) + (name : String) (params ret : List String) (body : List YulStmt) : + legacyExecYulFuel fuel state (.stmt (YulStmt.funcDef name params ret body)) = + YulExecResult.continue state := by + cases fuel <;> simp [legacyExecYulFuel] + +private theorem preservation_execYulStmtsFuel_cons_funcDef (fuel : Nat) (state : YulState) + (name : String) (params ret : List String) (body rest : List YulStmt) : + execYulStmtsFuel (Nat.succ fuel) state (YulStmt.funcDef name params ret body :: rest) = + execYulStmtsFuel fuel state rest := by + simp only [execYulStmtsFuel, legacyExecYulFuel] + rw [preservation_legacyExecYulFuel_funcDef] + +private theorem preservation_emitYul_runtimeCode_eq (contract : IRContract) : + (Compiler.emitYul contract).runtimeCode = Compiler.runtimeCode contract := by + rfl + +private theorem preservation_evalYulExpr_selectorExpr (state : YulState) : + evalYulExpr state selectorExpr = some (state.selector % selectorModulus) := by + have hShiftModEq : selectorShift % evmModulus = selectorShift := by + have hShiftLtModulus : selectorShift < evmModulus := by + norm_num [selectorShift, evmModulus] + exact Nat.mod_eq_of_lt hShiftLtModulus + have hSelectorShiftLt256 : selectorShift < 256 := by + norm_num [selectorShift] + have hSelectorShiftNotGe256 : ¬ 256 ≤ selectorShift := Nat.not_le_of_lt hSelectorShiftLt256 + have hSelectorWordLt : + (state.selector % selectorModulus) * 2 ^ selectorShift < evmModulus := by + have hModLt : state.selector % selectorModulus < selectorModulus := by + exact Nat.mod_lt _ (by decide) + have hPowPos : 0 < 2 ^ selectorShift := by + exact Nat.pow_pos (a := 2) (n := selectorShift) (by decide) + have hMulLt : + (state.selector % selectorModulus) * 2 ^ selectorShift < + selectorModulus * 2 ^ selectorShift := by + exact Nat.mul_lt_mul_of_pos_right hModLt hPowPos + have hModulusSplit : selectorModulus * 2 ^ selectorShift = evmModulus := by + norm_num [selectorModulus, selectorShift, evmModulus, Nat.pow_add, Nat.mul_comm, + Nat.mul_left_comm, Nat.mul_assoc] + simpa [hModulusSplit] using hMulLt + have hSelectorWordMod : + ((state.selector % selectorModulus) * 2 ^ selectorShift) % evmModulus = + (state.selector % selectorModulus) * 2 ^ selectorShift := by + exact Nat.mod_eq_of_lt hSelectorWordLt + simp [selectorExpr, evalYulExpr, evalYulCall, evalYulExprs, + evalBuiltinCallWithBackendContext, Backends.evalBuiltinCallWithEvmYulLeanContext, + Backends.evalBuiltinCallViaEvmYulLean, + calldataloadWord, selectorWord, + hShiftModEq, hSelectorWordMod, hSelectorShiftNotGe256] + +private theorem preservation_evalYulExpr_selectorExpr_eq (state : YulState) + (hselector : state.selector < selectorModulus) : + evalYulExpr state selectorExpr = some state.selector := by + rw [preservation_evalYulExpr_selectorExpr] + simp [Nat.mod_eq_of_lt hselector] + +private theorem preservation_execYulStmtFuel_switch_match + (state : YulState) (expr : YulExpr) (cases' : List (Prod Nat (List YulStmt))) + (defaultCase : Option (List YulStmt)) (fuel v : Nat) (body : List YulStmt) + (hEval : evalYulExpr state expr = some v) + (hFind : List.find? (fun (c, _) => c = v) cases' = some (v, body)) : + execYulStmtFuel (Nat.succ fuel) state (YulStmt.switch expr cases' defaultCase) = + execYulStmtsFuel fuel state body := by + cases fuel with + | zero => + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind] + | succ fuel => + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind] + +private def preservation_execYulStmtFuel_switch_miss_result (state : YulState) (fuel : Nat) + (defaultCase : Option (List YulStmt)) : YulExecResult := + match defaultCase with + | some body => execYulStmtsFuel fuel state body + | none => YulExecResult.continue state + +private theorem preservation_execYulStmtFuel_switch_miss + (state : YulState) (expr : YulExpr) (cases' : List (Prod Nat (List YulStmt))) + (defaultCase : Option (List YulStmt)) (fuel v : Nat) + (hEval : evalYulExpr state expr = some v) + (hFind : List.find? (fun (c, _) => c = v) cases' = none) : + execYulStmtFuel (Nat.succ fuel) state (YulStmt.switch expr cases' defaultCase) = + preservation_execYulStmtFuel_switch_miss_result state fuel defaultCase := by + cases fuel with + | zero => + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind, + preservation_execYulStmtFuel_switch_miss_result] + rfl + | succ fuel => + simp [execYulStmtFuel, execYulStmtsFuel, legacyExecYulFuel, hEval, hFind, + preservation_execYulStmtFuel_switch_miss_result] + rfl + +private theorem preservation_find_switch_case_of_find_function + (fns : List IRFunction) (sel : Nat) (fn : IRFunction) + (hFind : fns.find? (fun f => f.selector == sel) = some fn) : + (switchCases fns).find? (fun (c, _) => c = sel) = + some (fn.selector, switchCaseBody fn) := by + induction fns with + | nil => + simp at hFind + | cons f rest ih => + by_cases hsel : f.selector = sel + · have hselb : (f.selector == sel) = true := by + simp [hsel] + have hFind' : some f = some fn := by + simpa [List.find?, hselb] using hFind + cases hFind' + simp [switchCases, hsel] + · have hselb : (f.selector == sel) = false := by + simp [hsel] + have hFind' : rest.find? (fun f => f.selector == sel) = some fn := by + simpa [List.find?, hselb] using hFind + have ih' := ih hFind' + simpa [switchCases, List.find?, hsel] using ih' + +private theorem preservation_find_switch_case_of_find_function_eq_selector + (fns : List IRFunction) (sel : Nat) (fn : IRFunction) + (hFind : fns.find? (fun f => f.selector == sel) = some fn) : + (switchCases fns).find? (fun (c, _) => c = sel) = + some (sel, switchCaseBody fn) := by + have hCase := preservation_find_switch_case_of_find_function fns sel fn hFind + have hSel : fn.selector = sel := by + have h := List.find?_some hFind + simp at h + exact h + simpa [hSel] using hCase + +private theorem preservation_find_switch_case_of_find_function_none + (fns : List IRFunction) (sel : Nat) + (hFind : fns.find? (fun f => f.selector == sel) = none) : + (switchCases fns).find? (fun (c, _) => c = sel) = none := by + induction fns with + | nil => + simp at hFind + simp [switchCases] + | cons f rest ih => + by_cases hsel : f.selector = sel + · have hselb : (f.selector == sel) = true := by + simp [hsel] + have hFind' : (some f : Option IRFunction) = none := by + simp [List.find?, hselb] at hFind + cases hFind' + · have hselb : (f.selector == sel) = false := by + simp [hsel] + have hFind' : rest.find? (fun f => f.selector == sel) = none := by + simpa [List.find?, hselb] using hFind + have ih' := ih hFind' + simpa [switchCases, List.find?, hsel] using ih' + +private theorem preservation_execYulStmtsFuel_funcDefs_then_suffix (fuel : Nat) (state : YulState) + (prefix_ : List YulStmt) (suffix_ : List YulStmt) + (hFuncDefs : ∀ s ∈ prefix_, ∃ nm p r b, s = YulStmt.funcDef nm p r b) : + execYulStmtsFuel (prefix_.length + fuel) state (prefix_ ++ suffix_) = + execYulStmtsFuel fuel state suffix_ := by + induction prefix_ generalizing state with + | nil => simp + | cons h t ih => + have hmem : h ∈ h :: t := .head t + obtain ⟨nm, p, r, b, rfl⟩ := hFuncDefs h hmem + simp only [List.cons_append, List.length_cons] + conv_lhs => rw [show t.length + 1 + fuel = Nat.succ (t.length + fuel) from by omega] + rw [preservation_execYulStmtsFuel_cons_funcDef] + exact ih state (fun s hs => hFuncDefs s (List.mem_cons_of_mem _ hs)) + +private theorem preservation_execYulStmtsFuel_funcDefs_then_suffix_ge + (fuel : Nat) (state : YulState) + (prefix_ : List YulStmt) (suffix_ : List YulStmt) + (hFuncDefs : ∀ s ∈ prefix_, ∃ nm p r b, s = YulStmt.funcDef nm p r b) + (hFuel : fuel ≥ prefix_.length) : + execYulStmtsFuel fuel state (prefix_ ++ suffix_) = + execYulStmtsFuel (fuel - prefix_.length) state suffix_ := by + have : fuel = prefix_.length + (fuel - prefix_.length) := by omega + conv_lhs => rw [this] + exact preservation_execYulStmtsFuel_funcDefs_then_suffix _ state prefix_ suffix_ hFuncDefs @[simp] private theorem evalYulExpr_selectorExpr_initial (tx : YulTransaction) (state : IRState) (hselector : tx.functionSelector < selectorModulus) : evalYulExpr (initialYulState tx state) selectorExpr = some tx.functionSelector := by - simpa using (evalYulExpr_selectorExpr_eq (initialYulState tx state) hselector) + simpa using (preservation_evalYulExpr_selectorExpr_eq (initialYulState tx state) hselector) /-- Well-formedness: all internalFunctions are funcDef statements. -/ -def ContractWF (contract : IRContract) : Prop := +private def ContractWF (contract : IRContract) : Prop := ∀ s ∈ contract.internalFunctions, ∃ n p r b, s = YulStmt.funcDef n p r b private theorem runtimeCode_prefix_allFuncDefs (contract : IRContract) @@ -304,7 +510,7 @@ private theorem sizeOf_buildSwitch_ge_fn_body /-- Simplification: 1 ≠ 0 for if_ branch. -/ @[simp] private theorem one_ne_zero : (1 : Nat) ≠ 0 := by omega -/-- Identity simplifier for result-shaped matches emitted by `execYulFuel` reductions. -/ +/-- Identity simplifier for result-shaped matches emitted by `legacyExecYulFuel` reductions. -/ @[simp] private theorem yulExecResult_match_id (r : YulExecResult) : (match r with | .continue s => .continue s @@ -317,15 +523,15 @@ private theorem sizeOf_buildSwitch_ge_fn_body @[simp] private theorem execYulStmtsFuel_singleton_succ_bridge (fuel : Nat) (state : YulState) (stmt : YulStmt) : execYulStmtsFuel (fuel + 2) state [stmt] = execYulStmtFuel (fuel + 1) state stmt := by - simp [execYulStmtsFuel, execYulStmtFuel, execYulFuel] - cases hExec : execYulFuel (fuel + 1) state (.stmt stmt) <;> simp + simp [execYulStmtsFuel, execYulStmtFuel, legacyExecYulFuel] + cases hExec : legacyExecYulFuel (fuel + 1) state (.stmt stmt) <;> simp /-- Fueled `if_` step: a zero condition skips the body and continues unchanged. -/ @[simp] private theorem execYulStmtFuel_if_zero_continue_bridge (fuel : Nat) (state : YulState) (cond : YulExpr) (body : List YulStmt) (hEval : evalYulExpr state cond = some 0) : execYulStmtFuel (fuel + 1) state (YulStmt.if_ cond body) = .continue state := by - simp [execYulStmtFuel, execYulFuel, hEval] + simp [execYulStmtFuel, legacyExecYulFuel, hEval] /-- Fueled `if_` step: a nonzero condition executes the body with decremented fuel. -/ @[simp] private theorem execYulStmtFuel_if_nonzero_exec_bridge @@ -333,9 +539,9 @@ private theorem sizeOf_buildSwitch_ge_fn_body (hEval : evalYulExpr state cond = some v) (hNonzero : v ≠ 0) : execYulStmtFuel (fuel + 1) state (YulStmt.if_ cond body) = execYulStmtsFuel fuel state body := by simpa [execYulStmtsFuel] using - (by simp [execYulStmtFuel, execYulFuel, hEval, hNonzero] : + (by simp [execYulStmtFuel, legacyExecYulFuel, hEval, hNonzero] : execYulStmtFuel (fuel + 1) state (YulStmt.if_ cond body) = - execYulFuel fuel state (.stmts body)) + legacyExecYulFuel fuel state (.stmts body)) /-- Zero fuel on a non-empty statement list always reverts. -/ @[simp] private theorem execYulStmtsFuel_zero_of_ne_nil_bridge @@ -344,7 +550,7 @@ private theorem sizeOf_buildSwitch_ge_fn_body cases stmts with | nil => cases hNe rfl | cons stmt rest => - simp [execYulStmtsFuel, execYulFuel] + simp [execYulStmtsFuel, legacyExecYulFuel] /-- `callvalueGuard` is a no-op when the execution context observes zero `callvalue()` modulo `2^256`, matching `DispatchGuardsSafe`. -/ @@ -354,7 +560,7 @@ private theorem exec_callvalueGuard_noop (fuel : Nat) (state : YulState) YulExecResult.continue state := by have hCallvalue : evalYulExpr state (YulExpr.call "callvalue" []) = some 0 := by simp [hMsgValue, evalYulExpr, evalYulCall, evalYulExprs, - evalBuiltinCallWithBackendContext] + evalBuiltinCallWithBackendContext, Backends.evalBuiltinCallWithEvmYulLeanContext] have hstmt : execYulStmtFuel (fuel + 1) state Compiler.callvalueGuard = .continue state := by simpa [Compiler.callvalueGuard] using @@ -381,8 +587,8 @@ private theorem exec_calldatasizeGuard_revert_of_short_noWrap (YulExpr.call "lt" [YulExpr.call "calldatasize" [], YulExpr.lit (4 + numParams * 32)]) = some 1 := by simp [evalYulExpr, evalYulCall, evalYulExprs, evalBuiltinCallWithBackendContext, - evalBuiltinCallWithContext, hLtTrue, Nat.mod_eq_of_lt hDataNoWrap, - Nat.mod_eq_of_lt hParamNoWrap] + Backends.evalBuiltinCallWithEvmYulLeanContext, Backends.evalBuiltinCallViaEvmYulLean, + hLtTrue, Nat.mod_eq_of_lt hDataNoWrap, Nat.mod_eq_of_lt hParamNoWrap] have hguard : execYulStmtFuel (fuel + 1) state (Compiler.calldatasizeGuard numParams) = execYulStmtsFuel fuel state [YulStmt.expr (YulExpr.call "revert" [YulExpr.lit 0, YulExpr.lit 0])] := by @@ -399,7 +605,7 @@ private theorem exec_calldatasizeGuard_revert_of_short_noWrap exact execYulStmtsFuel_zero_of_ne_nil_bridge state [YulStmt.expr (YulExpr.call "revert" [YulExpr.lit 0, YulExpr.lit 0])] (by simp) | succ k => - cases k <;> simp [execYulFuel, execYulStmtsFuel, execYulStmtFuel] + cases k <;> simp [legacyExecYulFuel, execYulStmtsFuel, execYulStmtFuel] rw [execYulStmtsFuel_singleton_succ_bridge, hguard, hRevertBody] /-- If calldata has enough words for `numParams`, `calldatasizeGuard` is a no-op. @@ -421,7 +627,8 @@ private theorem exec_calldatasizeGuard_noop_of_noWrap (YulExpr.call "lt" [YulExpr.call "calldatasize" [], YulExpr.lit (4 + numParams * 32)]) = some 0 := by simp [evalYulExpr, evalYulCall, evalYulExprs, evalBuiltinCallWithBackendContext, - evalBuiltinCallWithContext, hLtFalse, Nat.mod_eq_of_lt hNoWrap, Nat.mod_eq_of_lt hParamNoWrap] + Backends.evalBuiltinCallWithEvmYulLeanContext, Backends.evalBuiltinCallViaEvmYulLean, + hLtFalse, Nat.mod_eq_of_lt hNoWrap, Nat.mod_eq_of_lt hParamNoWrap] have hstmt : execYulStmtFuel (fuel + 1) state (Compiler.calldatasizeGuard numParams) = .continue state := by simpa [Compiler.calldatasizeGuard] using @@ -448,7 +655,7 @@ Executing this with enough fuel steps through: 3. `1 ≠ 0` → second `if_` enters body containing the switch This reduction is proved mechanically below via bridge lemmas that avoid -`execYulFuel`'s `[reducible]` over-reduction into `Option.map`/`List.find?_map` +`legacyExecYulFuel`'s `[reducible]` over-reduction into `Option.map`/`List.find?_map` fusion forms. -/ @@ -462,7 +669,7 @@ private theorem eval_hasSelector_after_set (state : YulState) : (fuel : Nat) (state : YulState) (cond : YulExpr) (body : List YulStmt) (hEval : evalYulExpr state cond = some 0) : execYulStmtFuel (fuel + 1) state (YulStmt.if_ cond body) = .continue state := by - simp [execYulStmtFuel, execYulFuel, hEval] + simp [execYulStmtFuel, legacyExecYulFuel, hEval] /-- Fueled `if_` step: a nonzero condition executes the body with decremented fuel. -/ @[simp] private theorem execYulStmtFuel_if_nonzero_exec @@ -470,9 +677,9 @@ private theorem eval_hasSelector_after_set (state : YulState) : (hEval : evalYulExpr state cond = some v) (hNonzero : v ≠ 0) : execYulStmtFuel (fuel + 1) state (YulStmt.if_ cond body) = execYulStmtsFuel fuel state body := by simpa [execYulStmtsFuel] using - (by simp [execYulStmtFuel, execYulFuel, hEval, hNonzero] : + (by simp [execYulStmtFuel, legacyExecYulFuel, hEval, hNonzero] : execYulStmtFuel (fuel + 1) state (YulStmt.if_ cond body) = - execYulFuel fuel state (.stmts body)) + legacyExecYulFuel fuel state (.stmts body)) /-- Zero fuel on a non-empty statement list always reverts. -/ @[simp] private theorem execYulStmtsFuel_zero_of_ne_nil @@ -482,14 +689,14 @@ private theorem eval_hasSelector_after_set (state : YulState) : | nil => contradiction | cons _ _ => - simp [execYulStmtsFuel, execYulFuel] + simp [execYulStmtsFuel, legacyExecYulFuel] /-- Executing a singleton statement list consumes one list-step of fuel. -/ @[simp] private theorem execYulStmtsFuel_singleton_succ_local (fuel : Nat) (state : YulState) (stmt : YulStmt) : execYulStmtsFuel (fuel + 2) state [stmt] = execYulStmtFuel (fuel + 1) state stmt := by - simp [execYulStmtsFuel, execYulStmtFuel, execYulFuel] - cases hExec : execYulFuel (fuel + 1) state (.stmt stmt) <;> simp + simp [execYulStmtsFuel, execYulStmtFuel, legacyExecYulFuel] + cases hExec : legacyExecYulFuel (fuel + 1) state (.stmt stmt) <;> simp /-- Executing `[buildSwitch fns none none]` with enough fuel reduces to the singleton switch list when `calldatasize()` does not wrap modulo `2^256`. @@ -512,7 +719,8 @@ private theorem execBuildSwitch_none_none_aux_of_noWrap (fuel : Nat) (state : Yu (YulExpr.call "iszero" [YulExpr.call "lt" [YulExpr.call "calldatasize" [], YulExpr.lit 4]]) = some 1 := by simp [evalYulExpr, evalYulCall, evalYulExprs, evalBuiltinCallWithBackendContext, - evalBuiltinCallWithContext, Nat.mod_eq_of_lt hNoWrap, Nat.mod_eq_of_lt h4] + Backends.evalBuiltinCallWithEvmYulLeanContext, Backends.evalBuiltinCallViaEvmYulLean, + Nat.mod_eq_of_lt hNoWrap, Nat.mod_eq_of_lt h4] have hIdentEval : evalYulExpr state' (YulExpr.ident "__has_selector") = some 1 := by simpa [state', evalYulExpr] using eval_hasSelector_after_set state @@ -520,9 +728,10 @@ private theorem execBuildSwitch_none_none_aux_of_noWrap (fuel : Nat) (state : Yu evalYulExpr state' (YulExpr.call "iszero" [YulExpr.ident "__has_selector"]) = some 0 := by simp [evalYulExpr, evalYulCall, evalYulExprs, - evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext, hIdentEval] + evalBuiltinCallWithBackendContext, Backends.evalBuiltinCallWithEvmYulLeanContext, + Backends.evalBuiltinCallViaEvmYulLean, hIdentEval] rw [show fuel + 6 = (fuel + 4) + 2 by omega, execYulStmtsFuel_singleton_succ_local] - simp only [Compiler.CodegenCommon.buildSwitch, execYulStmtFuel, execYulFuel] + simp only [Compiler.CodegenCommon.buildSwitch, execYulStmtFuel, legacyExecYulFuel] simp [state', execYulStmtsFuel, hHasSelectorEval, hIfZeroEval, hIdentEval, switchCases, switchCaseBody, dispatchBody, selectorExpr, switchDefaultCase] exact yulExecResult_match_id _ @@ -531,8 +740,8 @@ private theorem execBuildSwitch_none_none_aux_of_noWrap (fuel : Nat) (state : Yu @[simp] private theorem execYulStmtsFuel_singleton_succ (fuel : Nat) (state : YulState) (stmt : YulStmt) : execYulStmtsFuel (fuel + 2) state [stmt] = execYulStmtFuel (fuel + 1) state stmt := by - simp [execYulStmtsFuel, execYulStmtFuel, execYulFuel] - cases hExec : execYulFuel (fuel + 1) state (.stmt stmt) <;> simp + simp [execYulStmtsFuel, execYulStmtFuel, legacyExecYulFuel] + cases hExec : legacyExecYulFuel (fuel + 1) state (.stmt stmt) <;> simp /-- If a head statement continues, the surrounding list steps into the tail. -/ @[simp] private theorem execYulStmtsFuel_cons_continue @@ -540,18 +749,18 @@ private theorem execBuildSwitch_none_none_aux_of_noWrap (fuel : Nat) (state : Yu (hstmt : execYulStmtFuel (fuel + 1) state stmt = .continue next) : execYulStmtsFuel (fuel + 2) state (stmt :: rest) = execYulStmtsFuel (fuel + 1) next rest := by - have hstmt' : execYulFuel (fuel + 1) state (.stmt stmt) = .continue next := by + have hstmt' : legacyExecYulFuel (fuel + 1) state (.stmt stmt) = .continue next := by simpa [execYulStmtFuel] using hstmt - simp [execYulStmtsFuel, execYulFuel, hstmt'] + simp [execYulStmtsFuel, legacyExecYulFuel, hstmt'] /-- If a head statement reverts, the surrounding list reverts immediately. -/ @[simp] private theorem execYulStmtsFuel_cons_revert (fuel : Nat) (state : YulState) (stmt : YulStmt) (rest : List YulStmt) (hstmt : execYulStmtFuel (fuel + 1) state stmt = .revert state) : execYulStmtsFuel (fuel + 2) state (stmt :: rest) = .revert state := by - have hstmt' : execYulFuel (fuel + 1) state (.stmt stmt) = .revert state := by + have hstmt' : legacyExecYulFuel (fuel + 1) state (.stmt stmt) = .revert state := by simpa [execYulStmtFuel] using hstmt - simp [execYulStmtsFuel, execYulFuel, hstmt'] + simp [execYulStmtsFuel, legacyExecYulFuel, hstmt'] /-- The case list emitted by `buildSwitch` is definitionally `switchCases`. Keeping this fact explicit helps avoid large reducible unfold chains in the @@ -600,7 +809,7 @@ private theorem evalSelectorExpr_setVar_has_selector (state : YulState) (v : Nat evalYulExpr (state.setVar "__has_selector" v) selectorExpr = some state.selector := by -- Keep this bridge local and avoid unfolding the full builtin evaluator. - simpa using (evalYulExpr_selectorExpr_eq (state.setVar "__has_selector" v) (by + simpa using (preservation_evalYulExpr_selectorExpr_eq (state.setVar "__has_selector" v) (by simpa [YulState.setVar] using hselector)) /-- In the non-payable branch, `DispatchGuardsSafe` forces `msgValue = 0 mod 2^256`. -/ @@ -643,7 +852,7 @@ private theorem exec_switchCaseBody_revert_of_short simpa [state, YulState.initial, YulState.setVar] using hNoWrap have hComment : execYulStmtFuel (fuel + 1) state (YulStmt.comment s!"{fn.name}()") = .continue state := by - simp [execYulStmtFuel, execYulFuel] + simp [execYulStmtFuel, legacyExecYulFuel] cases hPayable : fn.payable with | true => rw [show switchCaseBody fn = @@ -801,7 +1010,7 @@ private theorem exec_switchCaseBody_continue_of_long simpa [state, YulState.initial, YulState.setVar] using hLong have hComment : execYulStmtFuel (fuel + 1) state (YulStmt.comment s!"{fn.name}()") = .continue state := by - simp [execYulStmtFuel, execYulFuel] + simp [execYulStmtFuel, legacyExecYulFuel] cases hPayable : fn.payable with | true => rw [show switchCaseBody fn = @@ -890,19 +1099,19 @@ private theorem yulSwitchCasesLoopFree_mem /-- Key lemma: adding one unit of fuel does not change the result when the target is loop-free and fuel already exceeds the structural measure. -/ -private theorem execYulFuel_succ_eq +private theorem legacyExecYulFuel_succ_eq (target : YulExecTarget) (state : YulState) (fuel : Nat) (hLF : yulExecTargetLoopFree target = true) (hFuel : fuel ≥ sizeOfExecTarget target + 1) : - execYulFuel (fuel + 1) state target = execYulFuel fuel state target := by + legacyExecYulFuel (fuel + 1) state target = legacyExecYulFuel fuel state target := by -- Strong induction on sizeOf target. - -- The measure decreases at every recursive position in execYulFuel + -- The measure decreases at every recursive position in legacyExecYulFuel -- (stmt in a list, body of if/switch/block). Loop-free excludes for_. suffices ∀ (n : Nat) (target : YulExecTarget) (state : YulState) (fuel : Nat), sizeOf target = n → yulExecTargetLoopFree target = true → fuel ≥ sizeOfExecTarget target + 1 → - execYulFuel (fuel + 1) state target = execYulFuel fuel state target from + legacyExecYulFuel (fuel + 1) state target = legacyExecYulFuel fuel state target from this (sizeOf target) target state fuel rfl hLF hFuel intro n induction n using Nat.strongRecOn with @@ -939,11 +1148,11 @@ private theorem execYulFuel_succ_eq (by simp [yulExecTargetLoopFree, hLFs]) hs_fuel have ihr := fun s' => ih _ hr_lt (.stmts rest) s' (f + 1) rfl (by simp [yulExecTargetLoopFree, hLFr]) hr_fuel - show execYulFuel (f + 3) state (.stmts (s :: rest)) = - execYulFuel (f + 2) state (.stmts (s :: rest)) - simp only [execYulFuel] + show legacyExecYulFuel (f + 3) state (.stmts (s :: rest)) = + legacyExecYulFuel (f + 2) state (.stmts (s :: rest)) + simp only [legacyExecYulFuel] rw [ihs] - cases h : execYulFuel (f + 1) state (.stmt s) with + cases h : legacyExecYulFuel (f + 1) state (.stmt s) with | «continue» s' => exact ihr s' | «return» v s' => rfl | stop s' => rfl @@ -954,28 +1163,28 @@ private theorem execYulFuel_succ_eq | comment _ => have : fuel ≥ 1 := by simp only [sizeOfExecTarget] at hFuel; omega obtain ⟨f, rfl⟩ := Nat.exists_eq_succ_of_ne_zero (by omega : fuel ≠ 0) - simp [execYulFuel] + simp [legacyExecYulFuel] | let_ _ _ => have : fuel ≥ 1 := by simp only [sizeOfExecTarget] at hFuel; omega obtain ⟨f, rfl⟩ := Nat.exists_eq_succ_of_ne_zero (by omega : fuel ≠ 0) - simp [execYulFuel] + simp [legacyExecYulFuel] | letMany _ _ => have : fuel ≥ 1 := by simp only [sizeOfExecTarget] at hFuel; omega obtain ⟨f, rfl⟩ := Nat.exists_eq_succ_of_ne_zero (by omega : fuel ≠ 0) - simp [execYulFuel] + simp [legacyExecYulFuel] | assign _ _ => have : fuel ≥ 1 := by simp only [sizeOfExecTarget] at hFuel; omega obtain ⟨f, rfl⟩ := Nat.exists_eq_succ_of_ne_zero (by omega : fuel ≠ 0) - simp [execYulFuel] + simp [legacyExecYulFuel] | «leave» => have : fuel ≥ 1 := by simp only [sizeOfExecTarget] at hFuel; omega obtain ⟨f, rfl⟩ := Nat.exists_eq_succ_of_ne_zero (by omega : fuel ≠ 0) - simp [execYulFuel] - | funcDef _ _ _ _ => simp [execYulFuel] + simp [legacyExecYulFuel] + | funcDef _ _ _ _ => simp [legacyExecYulFuel] | expr e => have : fuel ≥ 1 := by simp only [sizeOfExecTarget] at hFuel; omega obtain ⟨f, rfl⟩ := Nat.exists_eq_succ_of_ne_zero (by omega : fuel ≠ 0) - simp [execYulFuel] + simp [legacyExecYulFuel] | if_ cond body => simp [yulStmtLoopFree] at hLF have : fuel ≥ 2 := by @@ -989,9 +1198,9 @@ private theorem execYulFuel_succ_eq simp only [sizeOfExecTarget] at hFuel ⊢ have : sizeOf body < sizeOf (YulStmt.if_ cond body) := by simp_wf omega - show execYulFuel (f + 3) state (.stmt (YulStmt.if_ cond body)) = - execYulFuel (f + 2) state (.stmt (YulStmt.if_ cond body)) - simp only [execYulFuel] + show legacyExecYulFuel (f + 3) state (.stmt (YulStmt.if_ cond body)) = + legacyExecYulFuel (f + 2) state (.stmt (YulStmt.if_ cond body)) + simp only [legacyExecYulFuel] cases evalYulExpr state cond with | none => rfl | some v => @@ -1008,9 +1217,9 @@ private theorem execYulFuel_succ_eq have : sizeOf expr < sizeOf (YulStmt.switch expr cases defaultCase) := by simp_wf; omega omega obtain ⟨f, rfl⟩ : ∃ f, fuel = f + 2 := ⟨fuel - 2, by omega⟩ - show execYulFuel (f + 3) state (.stmt (YulStmt.switch expr cases defaultCase)) = - execYulFuel (f + 2) state (.stmt (YulStmt.switch expr cases defaultCase)) - simp only [execYulFuel] + show legacyExecYulFuel (f + 3) state (.stmt (YulStmt.switch expr cases defaultCase)) = + legacyExecYulFuel (f + 2) state (.stmt (YulStmt.switch expr cases defaultCase)) + simp only [legacyExecYulFuel] cases evalYulExpr state expr with | none => rfl | some v => @@ -1062,9 +1271,9 @@ private theorem execYulFuel_succ_eq simp only [sizeOfExecTarget] at hFuel ⊢ have : sizeOf stmts < sizeOf (YulStmt.block stmts) := by simp_wf omega - show execYulFuel (f + 3) state (.stmt (YulStmt.block stmts)) = - execYulFuel (f + 2) state (.stmt (YulStmt.block stmts)) - simp only [execYulFuel] + show legacyExecYulFuel (f + 3) state (.stmt (YulStmt.block stmts)) = + legacyExecYulFuel (f + 2) state (.stmt (YulStmt.block stmts)) + simp only [legacyExecYulFuel] exact ih _ hb_lt (.stmts stmts) state (f + 1) rfl (by simp [yulExecTargetLoopFree, hLF]) hb_fuel | for_ _ _ _ _ => simp [yulStmtLoopFree] at hLF @@ -1085,7 +1294,7 @@ private theorem execYulStmtsFuel_fuel_adequate | zero => simp | succ k ihk => rw [show sizeOf body + 1 + (k + 1) = (sizeOf body + 1 + k) + 1 by omega] - rw [execYulFuel_succ_eq (.stmts body) state (sizeOf body + 1 + k) + rw [legacyExecYulFuel_succ_eq (.stmts body) state (sizeOf body + 1 + k) (by simp [yulExecTargetLoopFree, hLF]) (by simp [sizeOfExecTarget])] exact ihk @@ -1193,7 +1402,7 @@ private theorem SwitchCaseBodyBridge exact hmatch set_option maxHeartbeats 1600000000 in -/-- Main preservation theorem: Yul codegen preserves IR semantics. +/-- Legacy reference-oracle preservation theorem: Yul codegen preserves IR semantics. The `hWF` hypothesis requires that `contract.internalFunctions` are all `funcDef` statements, which holds for every contract emitted by the compiler. @@ -1202,7 +1411,7 @@ The `hWF` hypothesis requires that `contract.internalFunctions` are all `receiveEntrypoint = none` because `interpretIR` returns failure when no function selector matches, which is only consistent with a revert-only default case. Extending to fallback/receive requires extending `interpretIR`. -/ -theorem yulCodegen_preserves_semantics +private theorem yulCodegen_preserves_semantics_via_reference_oracle (contract : IRContract) (tx : IRTransaction) (initialState : IRState) (hselector : tx.functionSelector < selectorModulus) (hNoWrap : 4 + tx.args.length * 32 < evmModulus) @@ -1218,8 +1427,8 @@ theorem yulCodegen_preserves_semantics yulStmtsLoopFree fn.body = true) (hbody : ∀ fn, fn ∈ contract.functions → resultsMatch - (execIRFunction fn tx.args (initialState.withTx tx)) - (interpretYulBody fn tx (initialState.withTx tx))) : + (execIRFunction fn tx.args ({ initialState.withTx tx with returnValue := none })) + (interpretYulBody fn tx ({ initialState.withTx tx with returnValue := none }))) : resultsMatch (interpretIR contract tx initialState) (interpretYulFromIR contract tx initialState) := by @@ -1244,7 +1453,9 @@ theorem yulCodegen_preserves_semantics have hSkip : ∀ state : YulState, execYulStmtsFuel (sizeOf (prefix_ ++ [switchStmt]) + 1) state (prefix_ ++ [switchStmt]) = execYulStmtsFuel (sizeOf (prefix_ ++ [switchStmt]) + 1 - prefix_.length) state [switchStmt] := - fun state => execYulStmtsFuel_funcDefs_then_suffix_ge _ state prefix_ [switchStmt] hPrefixFD hFuel + fun state => + preservation_execYulStmtsFuel_funcDefs_then_suffix_ge _ state prefix_ [switchStmt] + hPrefixFD hFuel set adjustedFuel := sizeOf (prefix_ ++ [switchStmt]) + 1 - prefix_.length have hAdjGe : adjustedFuel ≥ 10 := by have : sizeOf (prefix_ ++ [switchStmt]) + 1 - prefix_.length ≥ sizeOf [switchStmt] + 1 := by @@ -1274,7 +1485,7 @@ theorem yulCodegen_preserves_semantics -- No function matches: IR returns failure, Yul should revert simp only [interpretIR, hFind] -- The Yul side: skip prefix, reach buildSwitch, step through block to switch, miss all cases, revert - simp only [interpretYulFromIR, emitYul_runtimeCode_eq, interpretYulRuntime, + simp only [interpretYulFromIR, preservation_emitYul_runtimeCode_eq, interpretYulRuntime, execYulStmts, hRuntimeEq, hSkip] rw [hm, hSwitchSimp] -- Use the buildSwitch stepping axiom @@ -1288,21 +1499,21 @@ theorem yulCodegen_preserves_semantics have hSelEval := evalSelectorExpr_setVar_has_selector yulInitState 1 (by rw [hSelEq]; exact hselector) -- Bridge hcase: tx.functionSelector = yulInitState.selector - have hcase := find_switch_case_of_find_function_none contract.functions + have hcase := preservation_find_switch_case_of_find_function_none contract.functions yulInitState.selector (hSelEq ▸ hFind) -- Apply switch miss lemma rw [show m + 2 + 1 = Nat.succ (m + 2) from by omega] - rw [execYulStmtFuel_switch_miss _ _ _ _ _ _ hSelEval hcase] + rw [preservation_execYulStmtFuel_switch_miss _ _ _ _ _ _ hSelEval hcase] -- Now we need to show the revert case matches resultsMatch for failure - simp [execYulStmtFuel_switch_miss_result, switchDefaultCase, - execYulStmtsFuel, execYulFuel, resultsMatch, + simp [preservation_execYulStmtFuel_switch_miss_result, switchDefaultCase, + execYulStmtsFuel, legacyExecYulFuel, resultsMatch, Compiler.Proofs.storageAsMappings, yulInitState, YulState.initial, YulState.setVar] | some fn => -- A function matches: use hbody to connect IR and Yul have hmem : fn ∈ contract.functions := List.mem_of_find?_eq_some hFind have hmatch := hbody fn hmem simp only [interpretIR, hFind] - simp only [interpretYulFromIR, emitYul_runtimeCode_eq, interpretYulRuntime, + simp only [interpretYulFromIR, preservation_emitYul_runtimeCode_eq, interpretYulRuntime, execYulStmts, hRuntimeEq, hSkip] simp only [interpretYulBody_eq_runtime, interpretYulRuntime, execYulStmts] at hmatch rw [hm, hSwitchSimp] @@ -1319,12 +1530,13 @@ theorem yulCodegen_preserves_semantics have hcase : (switchCases contract.functions).find? (fun (c, _) => c = tx.functionSelector) = some (tx.functionSelector, switchCaseBody fn) := by simpa [hSelEq] using - (find_switch_case_of_find_function_eq_selector contract.functions yulInitState.selector fn + (preservation_find_switch_case_of_find_function_eq_selector + contract.functions yulInitState.selector fn (hSelEq ▸ hFind)) rw [← hSelEq] at hcase -- Apply switch match lemma rw [show m + 2 + 1 = Nat.succ (m + 2) from by omega] - rw [execYulStmtFuel_switch_match _ _ _ _ _ _ _ hSelEval hcase] + rw [preservation_execYulStmtFuel_switch_match _ _ _ _ _ _ _ hSelEval hcase] -- Establish fuel adequacy for the body bridge. -- sizeOf [switchStmt] ≥ sizeOf fn.body + 12 (by sizeOf_buildSwitch_ge_fn_body), -- adjustedFuel ≥ sizeOf [switchStmt] + 1, and m + 10 = adjustedFuel. @@ -1335,7 +1547,13 @@ theorem yulCodegen_preserves_semantics have := sizeOf_append_ge_length_add prefix_ [switchStmt]; omega omega by_cases hlen : fn.params.length ≤ tx.args.length - · simpa [hlen] using + · have hNoValueRevert : + ¬ (fn.payable = false ∧ ¬tx.msgValue % evmModulus = 0) := by + intro h + rcases (hdispatchGuardSafe fn hmem).1 with hPayable | hZeroValue + · simp [h.1] at hPayable + · exact h.2 hZeroValue + simpa [hlen, hNoValueRevert] using (SwitchCaseBodyBridge fn tx { initialState with sender := tx.sender @@ -1346,6 +1564,7 @@ theorem yulCodegen_preserves_semantics chainId := tx.chainId blobBaseFee := tx.blobBaseFee calldata := tx.args + returnValue := none selector := tx.functionSelector } (m + 2) (hHasSelectorDead fn hmem) (hNoHasSelector fn hmem) (hLoopFree fn hmem) hFuelBody (hdispatchGuardSafe fn hmem) hNoWrap hlen hmatch) @@ -1360,43 +1579,8 @@ theorem yulCodegen_preserves_semantics chainId := tx.chainId blobBaseFee := tx.blobBaseFee calldata := tx.args + returnValue := none selector := tx.functionSelector } m (hdispatchGuardSafe fn hmem) hNoWrap hlen) -/-! ## Complete Preservation Theorem - -This version of the preservation theorem discharges the `hbody` hypothesis -using the proven `all_stmts_equiv` and `ir_yul_function_equiv_from_state_of_stmt_equiv`. - -The remaining gap between `interpretYulBodyFromState` (fuel-based proof chain) and -`interpretYulBody` (used by the theorem above) requires bridging two -different Yul execution entry points. This bridging lemma documents that gap explicitly. - -**Proof chain** (complete — fuel adequacy eliminated, now internal): -1. `all_stmts_equiv` — every IR statement type is equivalent (StatementEquivalence.lean) -2. `execIRStmtsFuel_equiv_execYulStmtsFuel_of_stmt_equiv` — lifts to lists (Equivalence.lean) -3. `ir_yul_function_equiv_from_state_of_stmt_equiv` — function-level equivalence - (fuel adequacy is discharged internally via `rfl`) - -The theorem `ir_function_body_equiv` below demonstrates the complete chain for any -single function, and `yulCodegen_preserves_semantics` lifts it to full contracts. --/ - -/-- Any single IR function body produces equivalent results under fuel-based Yul execution. - -This is the instantiation of the proof chain with `all_stmts_equiv`, producing a -self-contained result for any function/args/state triple. Fuel adequacy is discharged -internally (it is `rfl` since the IR interpreter is total/fuel-based). --/ -theorem ir_function_body_equiv - (fn : IRFunction) (selector : Nat) (args : List Nat) (initialState : IRState) : - resultsMatch - (execIRFunction fn args initialState) - (interpretYulBodyFromState fn selector - (fn.params.zip args |>.foldl (fun s (p, v) => s.setVar p.name v) initialState) - initialState) := - ir_yul_function_equiv_from_state_of_stmt_equiv - (fun sel f st irSt yulSt => all_stmts_equiv sel f st irSt yulSt) - fn selector args initialState - end Compiler.Proofs.YulGeneration diff --git a/Compiler/Proofs/YulGeneration/README.md b/Compiler/Proofs/YulGeneration/README.md index b6158d2a4..8c8a04068 100644 --- a/Compiler/Proofs/YulGeneration/README.md +++ b/Compiler/Proofs/YulGeneration/README.md @@ -2,11 +2,15 @@ This directory contains the verification proofs for Layer 3 (IR → Yul) of the Verity compiler pipeline. -**Status**: Complete (PR #42). All statement equivalence proofs proven, universal dispatcher proven. +**Status**: Legacy reference-oracle stack complete; native EVMYulLean dispatcher +retargeting is in progress. The public end-to-end native target is now the +`EvmYul.Yul.callDispatcher` theorem stack in `Compiler/Proofs/EndToEnd.lean`, +not the fuel-parametric proof-interpreter preservation theorem in this +directory. ## File Overview -- **`Semantics.lean`** - Executable semantics for Yul execution +- **`ReferenceOracle/Semantics.lean`** - Legacy executable oracle for Yul execution - State model (variables, storage, mappings, memory, calldata) - Expression evaluation (arithmetic, selectors, storage access) - Statement execution with fuel-parametric recursion @@ -17,8 +21,10 @@ This directory contains the verification proofs for Layer 3 (IR → Yul) of the - `resultsMatch` - Final result equivalence predicate - `execIRStmtsFuel_equiv_execYulStmtsFuel_of_stmt_equiv` - Statement list composition theorem -- **`Preservation.lean`** - Main Layer 3 preservation theorem - - Proves Yul codegen preserves IR semantics +- **`Preservation.lean`** - Legacy Layer 3 preservation theorem + - Proves Yul codegen preserves IR semantics for the reference-oracle path + - Kept as regression evidence while public compiler-correctness wrappers + route through the native dispatcher stack - **`StatementEquivalence.lean`** - Statement-level equivalence proofs - All 8 statement types proven (assign, storage load/store, mapping load/store, conditional, return, revert) @@ -28,6 +34,19 @@ This directory contains the verification proofs for Layer 3 (IR → Yul) of the - **`Codegen.lean`** - Yul code generation helper lemmas - Switch case generation and selector mapping +- **`Backends/EvmYulLeanNativeHarness.lean`** - Native EVMYulLean execution + harness + - Lowers emitted runtime code to executable EVMYulLean contracts + - Provides the native `callDispatcher` result surface used by the active + end-to-end theorem stack + +- **`Backends/EvmYulLeanRetarget.lean`** - Bridged-fragment backend equivalence + evidence + - Keeps proof-interpreter/EVMYulLean backend equivalence isolated to the + bridged fragment + - Does not export contract-level proof-interpreter preservation as public + compiler-correctness authority + - **`Lemmas.lean`** - General utility lemmas - **`PatchRulesProofs.lean`** - Proof hooks for deterministic Yul patch rules diff --git a/Compiler/Proofs/YulGeneration/ReferenceOracle/Builtins.lean b/Compiler/Proofs/YulGeneration/ReferenceOracle/Builtins.lean index 5fe0fc981..59341b75a 100644 --- a/Compiler/Proofs/YulGeneration/ReferenceOracle/Builtins.lean +++ b/Compiler/Proofs/YulGeneration/ReferenceOracle/Builtins.lean @@ -1,7 +1,7 @@ import Compiler.Constants import Compiler.Proofs.YulGeneration.Calldata import Compiler.Proofs.MappingSlot -import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanAdapter +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBuiltinSemantics import Verity.Core.Int256 import Verity.Core.Uint256 @@ -35,7 +35,7 @@ def natModPow (base exp modulus : Nat) : Nat := if modulus ≤ 1 then 0 else modPowAux modulus (base % modulus) exp 1 -def evalBuiltinCallWithContext +def legacyEvalBuiltinCallWithContext (storage : IRStorageSlot → IRStorageWord) (sender : Nat) (msgValue : Nat) @@ -253,7 +253,14 @@ inductive BuiltinBackend where | evmYulLean deriving DecidableEq, Repr -abbrev defaultBuiltinBackend : BuiltinBackend := .verity +/-- Explicit backend for Verity's historical reference-oracle interpreter. -/ +private abbrev legacyBuiltinBackend : BuiltinBackend := .verity + +/-- File-local default backend for native-retargeted reference-oracle helpers. -/ +private abbrev defaultBuiltinBackend : BuiltinBackend := .evmYulLean + +@[simp] private theorem defaultBuiltinBackend_eq_evmYulLean : + defaultBuiltinBackend = BuiltinBackend.evmYulLean := rfl def evalBuiltinCallWithBackendContext (backend : BuiltinBackend) @@ -271,44 +278,11 @@ def evalBuiltinCallWithBackendContext (argVals : List Nat) : Option Nat := match backend with | .verity => - evalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata func argVals + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata func argVals | .evmYulLean => - let toWord (x : Nat) : Nat := x % evmModulus - if func = "caller" then - match argVals with - | [] => some sender - | _ => none - else if func = "address" then - match argVals with - | [] => some (toWord thisAddress) - | _ => none - else if func = "callvalue" then - match argVals with - | [] => some (toWord msgValue) - | _ => none - else if func = "timestamp" then - match argVals with - | [] => some (toWord blockTimestamp) - | _ => none - else if func = "number" then - match argVals with - | [] => some (toWord blockNumber) - | _ => none - else if func = "chainid" then - match argVals with - | [] => some (toWord chainId) - | _ => none - else if func = "blobbasefee" then - match argVals with - | [] => some (toWord blobBaseFee) - | _ => none - else if func = "calldatasize" then - match argVals with - | [] => some (toWord (4 + calldata.length * 32)) - | _ => none - else - Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallViaEvmYulLean - storage sender selector calldata func argVals + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext + storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee + selector calldata func argVals def evalBuiltinCallWithBackend (backend : BuiltinBackend) @@ -320,86 +294,99 @@ def evalBuiltinCallWithBackend (argVals : List Nat) : Option Nat := evalBuiltinCallWithBackendContext backend storage sender 0 0 0 0 0 0 selector calldata func argVals -def evalBuiltinCall +def legacyEvalBuiltinCall + (storage : IRStorageSlot → IRStorageWord) + (sender : Nat) + (selector : Nat) + (calldata : List Nat) + (func : String) + (argVals : List Nat) : Option Nat := + legacyEvalBuiltinCallWithContext storage sender 0 0 0 0 0 0 selector calldata func argVals + +private def evalBuiltinCall (storage : IRStorageSlot → IRStorageWord) (sender : Nat) (selector : Nat) (calldata : List Nat) (func : String) (argVals : List Nat) : Option Nat := - evalBuiltinCallWithContext storage sender 0 0 0 0 0 0 selector calldata func argVals + evalBuiltinCallWithBackend defaultBuiltinBackend storage sender selector calldata func argVals -@[simp] theorem evalBuiltinCall_callvalue_nil +@[simp] private theorem evalBuiltinCall_callvalue_nil (storage : IRStorageSlot → IRStorageWord) (sender thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : - evalBuiltinCallWithContext storage sender 0 thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "callvalue" [] = + legacyEvalBuiltinCallWithContext storage sender 0 thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "callvalue" [] = some 0 := by - simp [evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCallWithContext] -@[simp] theorem evalBuiltinCall_callvalue_context +@[simp] private theorem evalBuiltinCall_callvalue_context (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : - evalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "callvalue" [] = + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "callvalue" [] = some (msgValue % evmModulus) := by - simp [evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCallWithContext] -@[simp] theorem evalBuiltinCall_calldatasize_nil +@[simp] private theorem evalBuiltinCall_calldatasize_nil (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) : - evalBuiltinCall storage sender selector calldata "calldatasize" [] = + evalBuiltinCall storage sender selector calldata "calldatasize" [] = some ((4 + calldata.length * 32) % evmModulus) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [evalBuiltinCall, evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, + Backends.evalBuiltinCallWithEvmYulLeanContext] -@[simp] theorem evalBuiltinCall_caller_nil +@[simp] private theorem evalBuiltinCall_caller_nil (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (calldata : List Nat) : evalBuiltinCall storage sender selector calldata "caller" [] = some sender := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [evalBuiltinCall, evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, + Backends.evalBuiltinCallWithEvmYulLeanContext] -@[simp] theorem evalBuiltinCall_address_nil +@[simp] private theorem evalBuiltinCall_address_nil (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : - evalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "address" [] = + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "address" [] = some (thisAddress % evmModulus) := by - simp [evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCallWithContext] -@[simp] theorem evalBuiltinCall_timestamp_nil +@[simp] private theorem evalBuiltinCall_timestamp_nil (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : - evalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "timestamp" [] = + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "timestamp" [] = some (blockTimestamp % evmModulus) := by - simp [evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCallWithContext] -@[simp] theorem evalBuiltinCall_number_nil +@[simp] private theorem evalBuiltinCall_number_nil (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : - evalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "number" [] = + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "number" [] = some (blockNumber % evmModulus) := by - simp [evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCallWithContext] -@[simp] theorem evalBuiltinCall_chainid_nil +@[simp] private theorem evalBuiltinCall_chainid_nil (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : - evalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "chainid" [] = + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "chainid" [] = some (chainId % evmModulus) := by - simp [evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCallWithContext] -@[simp] theorem evalBuiltinCall_blobbasefee_nil +@[simp] private theorem evalBuiltinCall_blobbasefee_nil (storage : IRStorageSlot → IRStorageWord) (sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector : Nat) (calldata : List Nat) : - evalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "blobbasefee" [] = + legacyEvalBuiltinCallWithContext storage sender msgValue thisAddress blockTimestamp blockNumber chainId blobBaseFee selector calldata "blobbasefee" [] = some (blobBaseFee % evmModulus) := by - simp [evalBuiltinCallWithContext] + simp [legacyEvalBuiltinCallWithContext] -@[simp] theorem calldataloadWord_offset4 +@[simp] private theorem calldataloadWord_offset4 (selector : Nat) (calldata : List Nat) : calldataloadWord selector calldata 4 = calldata.getD 0 0 % evmModulus := by simp [calldataloadWord] -@[simp] theorem evalBuiltinCall_calldataload_offset4_single +@[simp] private theorem evalBuiltinCall_calldataload_offset4_single (storage : IRStorageSlot → IRStorageWord) (sender selector value : Nat) : - evalBuiltinCall storage sender selector [value] "calldataload" [4] = some (value % evmModulus) := by - simp [evalBuiltinCall, evalBuiltinCallWithContext, calldataloadWord] + evalBuiltinCall storage sender selector [value] "calldataload" [4] = some (value % evmModulus) := by + simp [evalBuiltinCall, evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, + Backends.evalBuiltinCallWithEvmYulLeanContext, Backends.evalBuiltinCallViaEvmYulLean, + calldataloadWord] -@[simp] theorem evalBuiltinCallWithBackend_calldataload_offset4_single +@[simp] private theorem evalBuiltinCallWithBackend_calldataload_offset4_single (storage : IRStorageSlot → IRStorageWord) (sender selector value : Nat) : evalBuiltinCallWithBackend defaultBuiltinBackend @@ -410,16 +397,19 @@ def evalBuiltinCall "calldataload" [4] = some (value % evmModulus) := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext, + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, + Backends.evalBuiltinCallWithEvmYulLeanContext, Backends.evalBuiltinCallViaEvmYulLean, calldataloadWord] -@[simp] theorem evalBuiltinCall_sload_single +@[simp] private theorem evalBuiltinCall_sload_single (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (slot : Nat) : - evalBuiltinCall storage sender selector [] "sload" [slot] = + evalBuiltinCall storage sender selector [] "sload" [slot] = some (Compiler.Proofs.abstractLoadStorageOrMapping storage slot).toNat := by - simp [evalBuiltinCall, evalBuiltinCallWithContext] + simp [evalBuiltinCall, evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, + Backends.evalBuiltinCallWithEvmYulLeanContext, Backends.evalBuiltinCallViaEvmYulLean, + Compiler.Proofs.abstractLoadStorageOrMapping] -@[simp] theorem evalBuiltinCallWithBackend_sload_single +@[simp] private theorem evalBuiltinCallWithBackend_sload_single (storage : IRStorageSlot → IRStorageWord) (sender selector : Nat) (slot : Nat) : evalBuiltinCallWithBackend defaultBuiltinBackend @@ -430,6 +420,8 @@ def evalBuiltinCall "sload" [slot] = some (Compiler.Proofs.abstractLoadStorageOrMapping storage slot).toNat := by - simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, evalBuiltinCallWithContext] + simp [evalBuiltinCallWithBackend, evalBuiltinCallWithBackendContext, + Backends.evalBuiltinCallWithEvmYulLeanContext, Backends.evalBuiltinCallViaEvmYulLean, + Compiler.Proofs.abstractLoadStorageOrMapping] end Compiler.Proofs.YulGeneration diff --git a/Compiler/Proofs/YulGeneration/ReferenceOracle/Semantics.lean b/Compiler/Proofs/YulGeneration/ReferenceOracle/Semantics.lean index 4037356cd..bc2891781 100644 --- a/Compiler/Proofs/YulGeneration/ReferenceOracle/Semantics.lean +++ b/Compiler/Proofs/YulGeneration/ReferenceOracle/Semantics.lean @@ -1,8 +1,8 @@ import Compiler.Yul.Ast import Compiler.Proofs.IRGeneration.IRInterpreter import Compiler.Proofs.MappingSlot +import Compiler.Proofs.YulGeneration.RuntimeTypes import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins -import Compiler.Proofs.YulGeneration.ReferenceOracle.State namespace Compiler.Proofs.YulGeneration @@ -14,7 +14,7 @@ open Compiler.Proofs /-! Reference oracle only. -This module preserves Verity's historical `execYulFuel` runtime semantics for +This module preserves Verity's historical `legacyExecYulFuel` runtime semantics for regression tests and bridge comparisons. EVMYulLean is the trusted semantic target for the current retargeting path; this file is not part of that trust boundary. @@ -22,18 +22,12 @@ boundary. /-! ## Yul Runtime Semantics (Layer 3 Foundation) -This module defines execution semantics for a Yul runtime program. It mirrors -IRInterpreter but models selector-aware calldata so `emitYul`'s runtime switch -behaves correctly. +This module defines the historical fuel-based execution semantics for a Yul +runtime program. Shared transaction/result/state plumbing lives in +`RuntimeTypes.lean` so native EVMYulLean proofs can use those data structures +without importing this legacy interpreter. -/ -/-- Selector expression used by the runtime switch. -/ -def selectorExpr : YulExpr := - YulExpr.call "shr" [ - YulExpr.lit selectorShift, - YulExpr.call "calldataload" [YulExpr.lit 0] - ] - /-! Runtime Yul mapping slots are derived via `keccak(baseSlot, key)`. Proof semantics call through `MappingSlot`; the active backend is `keccak` (see @@ -41,64 +35,6 @@ semantics call through `MappingSlot`; the active backend is `keccak` (see aligned with Solidity's keccak-derived flat storage slot layout. -/ -/-! ## Execution State -/ - -structure YulTransaction where - sender : Nat - msgValue : Nat := 0 - thisAddress : Nat := 0 - blockTimestamp : Nat := 0 - blockNumber : Nat := 0 - chainId : Nat := 0 - blobBaseFee : Nat := 0 - functionSelector : Nat - args : List Nat - deriving Repr - -/-- Convert an IR transaction to a Yul transaction. -/ -@[reducible] def YulTransaction.ofIR (tx : IRTransaction) : YulTransaction := - { sender := tx.sender - msgValue := tx.msgValue - thisAddress := tx.thisAddress - blockTimestamp := tx.blockTimestamp - blockNumber := tx.blockNumber - chainId := tx.chainId - blobBaseFee := tx.blobBaseFee - functionSelector := tx.functionSelector - args := tx.args } - -@[simp] theorem YulTransaction.ofIR_sender (tx : IRTransaction) : - (YulTransaction.ofIR tx).sender = tx.sender := rfl -@[simp] theorem YulTransaction.ofIR_args (tx : IRTransaction) : - (YulTransaction.ofIR tx).args = tx.args := rfl - -/-- Initial state for Yul execution. -/ -def YulState.initial (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) - (events : List (List Nat) := []) : YulState := - { vars := [] - storage := storage - transientStorage := fun _ => 0 - memory := fun _ => 0 - calldata := tx.args - selector := tx.functionSelector - returnValue := none - sender := tx.sender - msgValue := tx.msgValue - thisAddress := tx.thisAddress - blockTimestamp := tx.blockTimestamp - blockNumber := tx.blockNumber - chainId := tx.chainId - blobBaseFee := tx.blobBaseFee - events := events } - -/-- Lookup variable in state -/ -def YulState.getVar (s : YulState) (name : String) : Option Nat := - s.vars.find? (·.1 == name) |>.map (·.2) - -/-- Set variable in state -/ -def YulState.setVar (s : YulState) (name : String) (value : Nat) : YulState := - { s with vars := (name, value) :: s.vars.filter (·.1 != name) } - /-! ## Yul Expression Evaluation -/ /-! Size measures for termination proofs. -/ @@ -144,7 +80,7 @@ def evalYulCall (state : YulState) (func : String) : List YulExpr → Option Nat | _ => none else Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext - Compiler.Proofs.YulGeneration.defaultBuiltinBackend + Compiler.Proofs.YulGeneration.BuiltinBackend.evmYulLean state.storage state.sender state.msgValue state.thisAddress state.blockTimestamp state.blockNumber state.chainId state.blobBaseFee state.selector state.calldata func argVals termination_by args => exprsSize args + 1 @@ -185,18 +121,11 @@ def applyYulLogCall? (state : YulState) (func : String) some (state.appendYulLog offset size [topic0, topic1, topic2, topic3]) | _, _ => none -inductive YulExecResult - | continue (state : YulState) - | return (value : Nat) (state : YulState) - | stop (state : YulState) - | revert (state : YulState) - deriving Nonempty - inductive YulExecTarget | stmt (s : YulStmt) | stmts (ss : List YulStmt) -def execYulFuel : Nat → YulState → YulExecTarget → YulExecResult +def legacyExecYulFuel : Nat → YulState → YulExecTarget → YulExecResult | _, state, .stmts [] => .continue state | _, state, .stmt (YulStmt.funcDef _ _ _ _) => .continue state | 0, state, _ => .revert state @@ -285,52 +214,52 @@ def execYulFuel : Nat → YulState → YulExecTarget → YulExecResult if v = 0 then .continue state else - execYulFuel fuel state (.stmts body) + legacyExecYulFuel fuel state (.stmts body) | none => .revert state | .switch expr cases defaultCase => match evalYulExpr state expr with | some v => match cases.find? (fun x => decide (x.fst = v)) with - | some (_, body) => execYulFuel fuel state (.stmts body) + | some (_, body) => legacyExecYulFuel fuel state (.stmts body) | none => match defaultCase with - | some body => execYulFuel fuel state (.stmts body) + | some body => legacyExecYulFuel fuel state (.stmts body) | none => .continue state | none => .revert state | .for_ init cond post body => -- Execute init, then loop: check cond, run body, run post, repeat - match execYulFuel fuel state (.stmts init) with + match legacyExecYulFuel fuel state (.stmts init) with | .continue s' => match evalYulExpr s' cond with | some v => if v = 0 then .continue s' else - match execYulFuel fuel s' (.stmts body) with + match legacyExecYulFuel fuel s' (.stmts body) with | .continue s'' => - match execYulFuel fuel s'' (.stmts post) with + match legacyExecYulFuel fuel s'' (.stmts post) with | .continue s''' => - execYulFuel fuel s''' (.stmt (.for_ [] cond post body)) + legacyExecYulFuel fuel s''' (.stmt (.for_ [] cond post body)) | other => other | other => other | none => .revert s' | other => other - | .block stmts => execYulFuel fuel state (.stmts stmts) + | .block stmts => legacyExecYulFuel fuel state (.stmts stmts) | .funcDef _ _ _ _ => .continue state | .stmts [] => .continue state | .stmts (stmt :: rest) => - match execYulFuel fuel state (.stmt stmt) with - | .continue s' => execYulFuel fuel s' (.stmts rest) + match legacyExecYulFuel fuel state (.stmt stmt) with + | .continue s' => legacyExecYulFuel fuel s' (.stmts rest) | .return v s => .return v s | .stop s => .stop s | .revert s => .revert s def execYulStmtFuel (fuel : Nat) (state : YulState) (stmt : YulStmt) : YulExecResult := - execYulFuel fuel state (.stmt stmt) + legacyExecYulFuel fuel state (.stmt stmt) def execYulStmtsFuel (fuel : Nat) (state : YulState) (stmts : List YulStmt) : YulExecResult := - execYulFuel fuel state (.stmts stmts) + legacyExecYulFuel fuel state (.stmts stmts) set_option allowUnsafeReducibility true in -attribute [reducible] execYulFuel +attribute [reducible] legacyExecYulFuel noncomputable def execYulStmt (state : YulState) (stmt : YulStmt) : YulExecResult := @@ -339,13 +268,6 @@ noncomputable def execYulStmt (state : YulState) (stmt : YulStmt) : YulExecResul noncomputable def execYulStmts (state : YulState) (stmts : List YulStmt) : YulExecResult := execYulStmtsFuel (sizeOf stmts + 1) state stmts -structure YulResult where - success : Bool - returnValue : Option Nat - finalStorage : IRStorageSlot → IRStorageWord - finalMappings : Nat → Nat → IRStorageWord - events : List (List Nat) - /-- Execute a Yul runtime program with selector-aware calldata -/ noncomputable def interpretYulRuntime (runtimeCode : List YulStmt) (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) (events : List (List Nat) := []) : YulResult := diff --git a/Compiler/Proofs/YulGeneration/ReferenceOracle/State.lean b/Compiler/Proofs/YulGeneration/ReferenceOracle/State.lean index 50c4d1976..1694a1f16 100644 --- a/Compiler/Proofs/YulGeneration/ReferenceOracle/State.lean +++ b/Compiler/Proofs/YulGeneration/ReferenceOracle/State.lean @@ -1,27 +1,13 @@ -import Compiler.Proofs.IRGeneration.IRStorageWord +import Compiler.Proofs.YulGeneration.RuntimeTypes namespace Compiler.Proofs.YulGeneration -open Compiler.Proofs.IRGeneration (IRStorageWord IRStorageSlot) +/-! +Compatibility re-export for historical imports. -/-! Shared state structures for the reference-oracle Yul runtime. -/ - -structure YulState where - vars : List (String × Nat) - storage : IRStorageSlot → IRStorageWord - transientStorage : Nat → Nat := fun _ => 0 - memory : Nat → Nat - calldata : List Nat - selector : Nat - returnValue : Option Nat - sender : Nat - msgValue : Nat := 0 - thisAddress : Nat := 0 - blockTimestamp : Nat := 0 - blockNumber : Nat := 0 - chainId : Nat := 0 - blobBaseFee : Nat := 0 - events : List (List Nat) := [] - deriving Nonempty +`YulState` now lives in `Compiler.Proofs.YulGeneration.RuntimeTypes` so native +EVMYulLean proofs can use the shared state shape without importing a +reference-oracle module. +-/ end Compiler.Proofs.YulGeneration diff --git a/Compiler/Proofs/YulGeneration/RuntimeTypes.lean b/Compiler/Proofs/YulGeneration/RuntimeTypes.lean new file mode 100644 index 000000000..ce02622a8 --- /dev/null +++ b/Compiler/Proofs/YulGeneration/RuntimeTypes.lean @@ -0,0 +1,178 @@ +import Compiler.Yul.Ast +import Compiler.IR +import Compiler.Constants +import Compiler.Proofs.IRGeneration.IRRuntimeTypes +import Compiler.Proofs.MappingSlot + +namespace Compiler.Proofs.YulGeneration + +open Compiler +open Compiler.Yul +open Compiler.Proofs.IRGeneration +export Compiler.Constants (evmModulus selectorModulus selectorShift) + +/-! +Shared Yul runtime data structures. + +This module intentionally contains only neutral transaction/result/state +plumbing used by both the historical reference oracle and the native +EVMYulLean harness. It does not define or import the legacy fuel interpreter. +-/ + +structure YulState where + vars : List (String × Nat) + storage : IRStorageSlot → IRStorageWord + transientStorage : Nat → Nat := fun _ => 0 + memory : Nat → Nat + calldata : List Nat + selector : Nat + returnValue : Option Nat + sender : Nat + msgValue : Nat := 0 + thisAddress : Nat := 0 + blockTimestamp : Nat := 0 + blockNumber : Nat := 0 + chainId : Nat := 0 + blobBaseFee : Nat := 0 + events : List (List Nat) := [] + deriving Nonempty + +/-- Selector expression used by the runtime switch. -/ +def selectorExpr : YulExpr := + YulExpr.call "shr" [ + YulExpr.lit selectorShift, + YulExpr.call "calldataload" [YulExpr.lit 0] + ] + +structure YulTransaction where + sender : Nat + msgValue : Nat := 0 + thisAddress : Nat := 0 + blockTimestamp : Nat := 0 + blockNumber : Nat := 0 + chainId : Nat := 0 + blobBaseFee : Nat := 0 + functionSelector : Nat + args : List Nat + deriving Repr + +/-- Convert an IR transaction to a Yul transaction. -/ +@[reducible] def YulTransaction.ofIR (tx : IRTransaction) : YulTransaction := + { sender := tx.sender + msgValue := tx.msgValue + thisAddress := tx.thisAddress + blockTimestamp := tx.blockTimestamp + blockNumber := tx.blockNumber + chainId := tx.chainId + blobBaseFee := tx.blobBaseFee + functionSelector := tx.functionSelector + args := tx.args } + +/-! ### Loop-free syntactic predicates + +Decidable predicates checking that a Yul AST does not contain `for_` loops. +These are `Bool`-valued so compiler-generated fragments can discharge them +automatically via `rfl`. -/ +mutual +def yulStmtLoopFree : YulStmt → Bool + | .comment _ | .let_ _ _ | .letMany _ _ | .assign _ _ | .expr _ | .leave => true + | .if_ _ body => yulStmtsLoopFree body + | .for_ _ _ _ _ => false + | .switch _ cases defaultCase => + yulSwitchCasesLoopFree cases && yulOptionStmtsLoopFree defaultCase + | .block stmts => yulStmtsLoopFree stmts + | .funcDef _ _ _ body => yulStmtsLoopFree body + +def yulStmtsLoopFree : List YulStmt → Bool + | [] => true + | stmt :: stmts => yulStmtLoopFree stmt && yulStmtsLoopFree stmts + +def yulSwitchCasesLoopFree : List (Nat × List YulStmt) → Bool + | [] => true + | (_, body) :: rest => yulStmtsLoopFree body && yulSwitchCasesLoopFree rest + +def yulOptionStmtsLoopFree : Option (List YulStmt) → Bool + | none => true + | some body => yulStmtsLoopFree body +end + +/-- Preconditions under which generated dispatch guards behave like the + intended source-level checks for a selected function case. -/ +def DispatchGuardsSafe (fn : IRFunction) (tx : IRTransaction) : Prop := + (fn.payable = true ∨ tx.msgValue % evmModulus = 0) ∧ + 4 + fn.params.length * 32 < evmModulus + +@[simp] theorem YulTransaction.ofIR_sender (tx : IRTransaction) : + (YulTransaction.ofIR tx).sender = tx.sender := rfl + +@[simp] theorem YulTransaction.ofIR_args (tx : IRTransaction) : + (YulTransaction.ofIR tx).args = tx.args := rfl + +/-- Initial state for Yul execution. -/ +def YulState.initial (tx : YulTransaction) (storage : IRStorageSlot → IRStorageWord) + (events : List (List Nat) := []) : YulState := + { vars := [] + storage := storage + transientStorage := fun _ => 0 + memory := fun _ => 0 + calldata := tx.args + selector := tx.functionSelector + returnValue := none + sender := tx.sender + msgValue := tx.msgValue + thisAddress := tx.thisAddress + blockTimestamp := tx.blockTimestamp + blockNumber := tx.blockNumber + chainId := tx.chainId + blobBaseFee := tx.blobBaseFee + events := events } + +/-- Lookup variable in state. -/ +def YulState.getVar (s : YulState) (name : String) : Option Nat := + s.vars.find? (·.1 == name) |>.map (·.2) + +/-- Set variable in state. -/ +def YulState.setVar (s : YulState) (name : String) (value : Nat) : YulState := + { s with vars := (name, value) :: s.vars.filter (·.1 != name) } + +structure YulResult where + success : Bool + returnValue : Option Nat + finalStorage : IRStorageSlot → IRStorageWord + finalMappings : Nat → Nat → IRStorageWord + events : List (List Nat) + +inductive YulExecResult + | continue (state : YulState) + | return (value : Nat) (state : YulState) + | stop (state : YulState) + | revert (state : YulState) + deriving Nonempty + +def yulResultOfExecWithRollback (rollback : YulState) : YulExecResult → YulResult + | .continue s => + { success := true + returnValue := s.returnValue + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } + | .return v s => + { success := true + returnValue := some v + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } + | .stop s => + { success := true + returnValue := none + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } + | .revert _ => + { success := false + returnValue := none + finalStorage := rollback.storage + finalMappings := Compiler.Proofs.storageAsMappings rollback.storage + events := rollback.events } + +end Compiler.Proofs.YulGeneration diff --git a/Compiler/Proofs/YulGeneration/StatementEquivalence.lean b/Compiler/Proofs/YulGeneration/StatementEquivalence.lean index 446ae884c..68c209fc1 100644 --- a/Compiler/Proofs/YulGeneration/StatementEquivalence.lean +++ b/Compiler/Proofs/YulGeneration/StatementEquivalence.lean @@ -1,6 +1,6 @@ -import Compiler.Proofs.YulGeneration.Equivalence -import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics import Compiler.Proofs.IRGeneration.IRInterpreter +import Compiler.Proofs.YulGeneration.IRFuel +import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics namespace Compiler.Proofs.YulGeneration @@ -8,16 +8,87 @@ open Compiler open Compiler.Yul open Compiler.Proofs.IRGeneration +private def yulStateOfIR (_selector : Nat) (state : IRState) : YulState := + { vars := state.vars + storage := state.storage + transientStorage := state.transientStorage + memory := state.memory + calldata := state.calldata + selector := state.selector + returnValue := state.returnValue + sender := state.sender + msgValue := state.msgValue + thisAddress := state.thisAddress + blockTimestamp := state.blockTimestamp + blockNumber := state.blockNumber + chainId := state.chainId + blobBaseFee := state.blobBaseFee + events := state.events } + +private def statesAligned (selector : Nat) (ir : IRState) (yul : YulState) : Prop := + yul = yulStateOfIR selector ir + +private def execResultsAligned (selector : Nat) : IRExecResult → YulExecResult → Prop + | .continue ir, .continue yul => statesAligned selector ir yul + | .return v ir, .return v' yul => v = v' ∧ statesAligned selector ir yul + | .stop ir, .stop yul => statesAligned selector ir yul + | .revert ir, .revert yul => statesAligned selector ir yul + | _, _ => False + +private def execIRStmt_equiv_execYulStmt_goal + (selector : Nat) (fuel : Nat) (stmt : YulStmt) + (irState : IRState) (yulState : YulState) : Prop := + statesAligned selector irState yulState → + execResultsAligned selector + (execIRStmtFuel fuel irState stmt) (execYulStmtFuel fuel yulState stmt) + +private def execIRStmts_equiv_execYulStmts_goal + (selector : Nat) (fuel : Nat) (stmts : List YulStmt) + (irState : IRState) (yulState : YulState) : Prop := + statesAligned selector irState yulState → + execResultsAligned selector + (execIRStmtsFuel fuel irState stmts) (execYulStmtsFuel fuel yulState stmts) + /-! ## Layer 3: Statement-Level Equivalence (Complete) Proves that each IR statement type executes equivalently in Yul when states are aligned. Uses `mutual` recursion between `conditional_equiv` and `all_stmts_equiv` to handle the circular dependency. -Individual statement proofs compose via `execIRStmtsFuel_equiv_execYulStmtsFuel_of_stmt_equiv` -(Equivalence.lean) to complete the `hbody` hypothesis in `Preservation.lean`. +Individual statement proofs feed the file-local sequence/function lifting +helpers in `Equivalence.lean`; the statement-level legacy equivalence theorem +`all_stmts_equiv` remains file-local transition evidence. -/ +private theorem execYulStmtsFuel_cons + (fuel : Nat) (state : YulState) (stmt : YulStmt) (rest : List YulStmt) : + execYulStmtsFuel (Nat.succ fuel) state (stmt :: rest) = + match execYulStmtFuel fuel state stmt with + | .continue s' => execYulStmtsFuel fuel s' rest + | .return v s => .return v s + | .stop s => .stop s + | .revert s => .revert s := by + rfl + +private theorem execYulStmtFuel_for + (fuel : Nat) (state : YulState) (init : List YulStmt) (cond : YulExpr) (post body : List YulStmt) : + execYulStmtFuel (Nat.succ fuel) state (YulStmt.for_ init cond post body) = + match execYulStmtsFuel fuel state init with + | .continue s' => + match evalYulExpr s' cond with + | some v => + if v = 0 then .continue s' + else + match execYulStmtsFuel fuel s' body with + | .continue s'' => + match execYulStmtsFuel fuel s'' post with + | .continue s''' => execYulStmtFuel fuel s''' (.for_ [] cond post body) + | other => other + | other => other + | none => .revert s' + | other => other := by + rfl + /-! ### Expression Equivalence IR and Yul expression evaluators are total and structurally identical, @@ -29,7 +100,7 @@ mutual /-- IR and Yul expression evaluation are identical when states are aligned. Proved by mutual structural induction on expression size. -/ -theorem evalIRExpr_eq_evalYulExpr (selector : Nat) (irState : IRState) (expr : YulExpr) : +private theorem evalIRExpr_eq_evalYulExpr (selector : Nat) (irState : IRState) (expr : YulExpr) : evalIRExpr irState expr = evalYulExpr (yulStateOfIR selector irState) expr := by match expr with | .lit n => simp only [evalIRExpr, evalYulExpr] @@ -46,7 +117,7 @@ decreasing_by /-- List version: IR and Yul list evaluation are identical when states are aligned. Follows from `evalIRExpr_eq_evalYulExpr` by structural induction on the list. -/ -theorem evalIRExprs_eq_evalYulExprs (selector : Nat) (irState : IRState) (exprs : List YulExpr) : +private theorem evalIRExprs_eq_evalYulExprs (selector : Nat) (irState : IRState) (exprs : List YulExpr) : evalIRExprs irState exprs = evalYulExprs (yulStateOfIR selector irState) exprs := by match exprs with | [] => simp only [evalIRExprs, evalYulExprs] @@ -61,7 +132,7 @@ decreasing_by omega /-- Call version: IR and Yul call evaluation are identical when states are aligned. -/ -theorem evalIRCall_eq_evalYulCall (selector : Nat) (irState : IRState) (func : String) (args : List YulExpr) : +private theorem evalIRCall_eq_evalYulCall (selector : Nat) (irState : IRState) (func : String) (args : List YulExpr) : evalIRCall irState func args = evalYulCall (yulStateOfIR selector irState) func args := by simp only [evalIRCall, evalYulCall] rw [evalIRExprs_eq_evalYulExprs selector irState args] @@ -132,7 +203,7 @@ private theorem execResultsAligned_log_call cases IRGeneration.applyYulLogCall? irState func argVals <;> simp [execResultsAligned, statesAligned] -theorem assign_equiv (selector : Nat) (fuel : Nat) (varName : String) (valueExpr : YulExpr) +private theorem assign_equiv (selector : Nat) (fuel : Nat) (varName : String) (valueExpr : YulExpr) (irState : IRState) (yulState : YulState) (halign : statesAligned selector irState yulState) (hfuel : fuel > 0) : @@ -146,7 +217,7 @@ theorem assign_equiv (selector : Nat) (fuel : Nat) (varName : String) (valueExpr cases fuel with | zero => contradiction | succ fuel' => - simp only [execIRStmtFuel, execIRStmt, execYulStmtFuel, execYulFuel] + simp only [execIRStmtFuel, execIRStmt, execYulStmtFuel, legacyExecYulFuel] -- Use lemma: evalIRExpr irState expr = evalYulExpr (yulStateOfIR selector irState) expr rw [evalIRExpr_eq_evalYulExpr] -- Now both sides are identical @@ -199,11 +270,11 @@ private theorem stmt_and_stmts_equiv : · intro selector stmt irState yulState halign cases stmt <;> simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel, execResultsAligned, halign] + execYulStmtFuel, legacyExecYulFuel, execResultsAligned, halign] · intro selector stmts irState yulState halign cases stmts <;> simp only [execIRStmtsFuel, execIRStmts, - execYulStmtsFuel, execYulFuel, execResultsAligned, halign] + execYulStmtsFuel, legacyExecYulFuel, execResultsAligned, halign] | succ fuel ih => rcases ih with ⟨ihStmt, ihStmts⟩ constructor @@ -213,24 +284,24 @@ private theorem stmt_and_stmts_equiv : cases stmt with | comment _ => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel, execResultsAligned, statesAligned, yulStateOfIR] + execYulStmtFuel, legacyExecYulFuel, execResultsAligned, statesAligned, yulStateOfIR] | let_ name value => exact assign_equiv selector (fuel + 1) name value irState (yulStateOfIR selector irState) rfl (by omega) | letMany _ _ => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel, execResultsAligned, statesAligned, yulStateOfIR] + execYulStmtFuel, legacyExecYulFuel, execResultsAligned, statesAligned, yulStateOfIR] | assign name value => exact assign_equiv selector (fuel + 1) name value irState (yulStateOfIR selector irState) rfl (by omega) | «leave» => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel, execResultsAligned, statesAligned, yulStateOfIR] + execYulStmtFuel, legacyExecYulFuel, execResultsAligned, statesAligned, yulStateOfIR] | expr e => cases e with | call func args => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel] + execYulStmtFuel, legacyExecYulFuel] -- Both sides match on (.call func args) against string literals. -- With `func` free, neither match tree reduces. Generalize so both -- sides share the same discriminant, then split. @@ -277,26 +348,26 @@ private theorem stmt_and_stmts_equiv : split <;> simp_all only [execResultsAligned, statesAligned, yulStateOfIR, and_self, and_true, true_and, Option.some.injEq] | lit val => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel, evalIRExpr, evalYulExpr, + execYulStmtFuel, legacyExecYulFuel, evalIRExpr, evalYulExpr, execResultsAligned, statesAligned, yulStateOfIR] | hex val => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel, evalIRExpr, evalYulExpr, + execYulStmtFuel, legacyExecYulFuel, evalIRExpr, evalYulExpr, execResultsAligned, statesAligned, yulStateOfIR] | str val => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel, evalIRExpr, evalYulExpr, + execYulStmtFuel, legacyExecYulFuel, evalIRExpr, evalYulExpr, execResultsAligned, statesAligned, yulStateOfIR] | ident val => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel, evalIRExpr, evalYulExpr, + execYulStmtFuel, legacyExecYulFuel, evalIRExpr, evalYulExpr, IRState.getVar, YulState.getVar, execResultsAligned, statesAligned, yulStateOfIR] cases hfind : List.find? (fun x => x.1 == val) irState.vars <;> simp only [Option.map] | if_ cond body => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel] + execYulStmtFuel, legacyExecYulFuel] rw [evalIRExpr_eq_evalYulExpr] cases hcond : evalYulExpr (yulStateOfIR selector irState) cond with | none => @@ -310,7 +381,7 @@ private theorem stmt_and_stmts_equiv : exact ihStmts selector body irState (yulStateOfIR selector irState) rfl | «switch» expr cases defaultCase => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel, beq_eq_decide, yulStateOfIR] + execYulStmtFuel, legacyExecYulFuel, beq_eq_decide, yulStateOfIR] rw [evalIRExpr_eq_evalYulExpr] cases hEval : evalYulExpr (yulStateOfIR selector irState) expr with | none => @@ -350,12 +421,12 @@ private theorem stmt_and_stmts_equiv : | none => simp only [execResultsAligned, statesAligned, yulStateOfIR] | some body => - simpa only [hEval', hFind', execYulStmtsFuel, execYulFuel] using + simpa only [hEval', hFind', execYulStmtsFuel, legacyExecYulFuel] using ihStmts selector body irState (yulStateOfIR selector irState) rfl | some pair => cases pair with | mk _ body => - simpa only [hEval', hFind, execYulStmtsFuel, execIRStmtsFuel, execYulFuel] using + simpa only [hEval', hFind, execYulStmtsFuel, execIRStmtsFuel, legacyExecYulFuel] using ihStmts selector body irState (yulStateOfIR selector irState) rfl | for_ init cond post body => simp only [execIRStmtFuel, @@ -561,18 +632,18 @@ private theorem stmt_and_stmts_equiv : and_self, and_true, true_and] | block stmts => simpa only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel] using + execYulStmtFuel, legacyExecYulFuel] using ihStmts selector stmts irState (yulStateOfIR selector irState) rfl | funcDef _ _ _ _ => simp only [execIRStmtFuel, execIRStmt, - execYulStmtFuel, execYulFuel, execResultsAligned, statesAligned, yulStateOfIR] + execYulStmtFuel, legacyExecYulFuel, execResultsAligned, statesAligned, yulStateOfIR] · intro selector stmts irState yulState halign unfold statesAligned at halign subst halign cases stmts with | nil => simp only [execIRStmtsFuel, execIRStmts, - execYulStmtsFuel, execYulFuel, execResultsAligned, statesAligned, yulStateOfIR] + execYulStmtsFuel, legacyExecYulFuel, execResultsAligned, statesAligned, yulStateOfIR] | cons stmt rest => have hStmt := ihStmt selector stmt irState (yulStateOfIR selector irState) rfl cases hIR : execIRStmtFuel fuel irState stmt with @@ -624,12 +695,12 @@ private theorem stmt_and_stmts_equiv : | «stop» _ => exact False.elim (stmt_align_contra (hStmt := hStmt) (hIR := hIR) (hYul := hYul) (by simp only [execResultsAligned, not_false_eq_true])) -theorem all_stmts_equiv : ∀ selector fuel stmt irState yulState, +private theorem all_stmts_equiv : ∀ selector fuel stmt irState yulState, execIRStmt_equiv_execYulStmt_goal selector fuel stmt irState yulState := by intro selector fuel stmt irState yulState exact (stmt_and_stmts_equiv fuel).1 selector stmt irState yulState -theorem conditional_equiv (selector : Nat) (fuel : Nat) +private theorem conditional_equiv (selector : Nat) (fuel : Nat) (condExpr : YulExpr) (body : List YulStmt) (irState : IRState) (yulState : YulState) (halign : statesAligned selector irState yulState) @@ -640,7 +711,7 @@ theorem conditional_equiv (selector : Nat) (fuel : Nat) simpa only [execIRStmt_equiv_execYulStmt_goal] using (all_stmts_equiv selector fuel (YulStmt.if_ condExpr body) irState yulState halign) -theorem return_equiv (selector : Nat) (fuel : Nat) +private theorem return_equiv (selector : Nat) (fuel : Nat) (offsetExpr sizeExpr : YulExpr) (irState : IRState) (yulState : YulState) (halign : statesAligned selector irState yulState) @@ -651,7 +722,7 @@ theorem return_equiv (selector : Nat) (fuel : Nat) simpa only [execIRStmt_equiv_execYulStmt_goal] using (all_stmts_equiv selector fuel (YulStmt.expr (.call "return" [offsetExpr, sizeExpr])) irState yulState halign) -theorem revert_equiv (selector : Nat) (fuel : Nat) +private theorem revert_equiv (selector : Nat) (fuel : Nat) (offsetExpr sizeExpr : YulExpr) (irState : IRState) (yulState : YulState) (halign : statesAligned selector irState yulState) @@ -662,7 +733,7 @@ theorem revert_equiv (selector : Nat) (fuel : Nat) simpa only [execIRStmt_equiv_execYulStmt_goal] using (all_stmts_equiv selector fuel (YulStmt.expr (.call "revert" [offsetExpr, sizeExpr])) irState yulState halign) -theorem storageStore_equiv (selector : Nat) (fuel : Nat) +private theorem storageStore_equiv (selector : Nat) (fuel : Nat) (slotExpr valExpr : YulExpr) (irState : IRState) (yulState : YulState) (halign : statesAligned selector irState yulState) diff --git a/Compiler/SimpleStorageNativeWitness.lean b/Compiler/SimpleStorageNativeWitness.lean index 2b7381680..d52b6681d 100644 --- a/Compiler/SimpleStorageNativeWitness.lean +++ b/Compiler/SimpleStorageNativeWitness.lean @@ -32,11 +32,6 @@ theorem lowerRuntimeContractNative_ok : rw [hLower] at this cases this -@[simp] theorem generatedRuntimeNativeFragment_eq : - Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment - (Compiler.emitYul simpleStorageIRContract).runtimeCode = true := by - native_decide - /-- The concrete lowered native contract for `simpleStorage`. Keeping this definition executable lets downstream concrete proofs reduce the diff --git a/Contracts/MacroTranslateInvariantTest.lean b/Contracts/MacroTranslateInvariantTest.lean index b4336db83..865897346 100644 --- a/Contracts/MacroTranslateInvariantTest.lean +++ b/Contracts/MacroTranslateInvariantTest.lean @@ -1,6 +1,8 @@ import Compiler.ABI +import Compiler.Codegen import Compiler.Proofs.IRGeneration.IRInterpreter -import Compiler.Proofs.YulGeneration.Equivalence +import Compiler.Proofs.YulGeneration.IRFuel +import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics import Compiler.Selector import Compiler.Hex import Contracts @@ -21,6 +23,10 @@ open Compiler.Hex open Compiler.Proofs.IRGeneration open Compiler.Proofs.YulGeneration +/- This executable harness is a legacy IR/reference-oracle differential + regression test. It is intentionally kept outside the public compiler + correctness theorem chain. -/ + private def contains (haystack needle : String) : Bool := let h := haystack.toList let n := needle.toList @@ -218,6 +224,20 @@ private def interpretIRFuelResult (contract : IRContract) (tx : IRTransaction) ( finalMappings := Compiler.Proofs.storageAsMappings state.storage events := state.events } +private def resultsMatchOn + (slots : List Nat) + (mappingKeys : List (Nat × Nat)) + (ir : IRResult) + (yul : YulResult) : Bool := + ir.success == yul.success && + ir.returnValue == yul.returnValue && + ir.events == yul.events && + slots.all (fun slotIdx => + ir.finalStorage (IRStorageSlot.ofNat slotIdx) == + yul.finalStorage (IRStorageSlot.ofNat slotIdx)) && + mappingKeys.all (fun (base, key) => + ir.finalMappings base key == yul.finalMappings base key) + private def interpretYulFromIRFuelResult (contract : IRContract) (tx : IRTransaction) (state : IRState) (fuel : Nat) : YulResult := let yulTx : YulTransaction := { diff --git a/Contracts/MacroTranslateRoundTripFuzz.lean b/Contracts/MacroTranslateRoundTripFuzz.lean index c6cb19b5e..28c726ded 100644 --- a/Contracts/MacroTranslateRoundTripFuzz.lean +++ b/Contracts/MacroTranslateRoundTripFuzz.lean @@ -1,6 +1,7 @@ +import Compiler.Proofs.YulGeneration.IRFuel import Compiler.Selector import Compiler.Hex -import Compiler.Proofs.YulGeneration.Equivalence +import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics import Contracts import Contracts.ProxyUpgradeabilityMacroSmoke import Contracts.ProxyUpgradeabilityLayoutCompatibleSmoke @@ -16,6 +17,53 @@ open Compiler.CompilationModel open Compiler.Proofs.IRGeneration open Compiler.Proofs.YulGeneration +/- This executable harness compares IR execution with the legacy reference-oracle + fuel interpreter as regression coverage only. It is not theorem authority for + native EVMYulLean correctness. -/ + +private def yulStateOfIR (_selector : Nat) (state : IRState) : YulState := + { vars := state.vars + «storage» := state.storage + transientStorage := state.transientStorage + memory := state.memory + calldata := state.calldata + selector := state.selector + returnValue := state.returnValue + sender := state.sender + msgValue := state.msgValue + thisAddress := state.thisAddress + blockTimestamp := state.blockTimestamp + blockNumber := state.blockNumber + chainId := state.chainId + blobBaseFee := state.blobBaseFee + events := state.events } + +private def yulResultOfExecWithRollback (rollback : YulState) : YulExecResult → YulResult + | .continue s => + { success := true + returnValue := s.returnValue + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } + | .return v s => + { success := true + returnValue := some v + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } + | .stop s => + { success := true + returnValue := none + finalStorage := s.storage + finalMappings := Compiler.Proofs.storageAsMappings s.storage + events := s.events } + | .revert _ => + { success := false + returnValue := none + finalStorage := rollback.storage + finalMappings := Compiler.Proofs.storageAsMappings rollback.storage + events := rollback.events } + private def expectTrue (label : String) (ok : Bool) : IO Unit := do if !ok then throw (IO.userError s!"round-trip fuzz failed: {label}") diff --git a/PrintAxioms.lean b/PrintAxioms.lean index 6954bf8d9..01e299f2d 100644 --- a/PrintAxioms.lean +++ b/PrintAxioms.lean @@ -36,9 +36,11 @@ import Compiler.Proofs.EventSemantics import Compiler.Proofs.HelperStepProofs import Compiler.Proofs.IRGeneration.Contract import Compiler.Proofs.IRGeneration.ContractFeatureTest +import Compiler.Proofs.IRGeneration.ContractShape import Compiler.Proofs.IRGeneration.Dispatch import Compiler.Proofs.IRGeneration.Function import Compiler.Proofs.IRGeneration.FunctionBody +import Compiler.Proofs.IRGeneration.FunctionShape import Compiler.Proofs.IRGeneration.GenericInduction import Compiler.Proofs.IRGeneration.IRInterpreter import Compiler.Proofs.IRGeneration.IRStorageWord @@ -52,14 +54,18 @@ import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanAdapter import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanAdapterCorrectness import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBodyClosure import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeLemmas +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgePredicates import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanNativeHarness +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanNativeSignedArithLemmas +import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanPureBuiltinLemmas import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanRetarget import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanSignedArithSpec import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanSourceExprClosure import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanStateBridge import Compiler.Proofs.YulGeneration.Equivalence +import Compiler.Proofs.YulGeneration.IRFuel import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins -import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics +import Compiler.Proofs.YulGeneration.RuntimeTypes import Lean import Lean.Util.FoldConsts @@ -833,132 +839,642 @@ end Verity.AxiomAudit Compiler.Proofs.ArithmeticProfile.shr_bridge -- Compiler/Proofs/EndToEnd.lean - Compiler.Proofs.EndToEnd.nativeResultsMatchOn_ok_of_resultsMatch_of_yulResultsAgreeOn - Compiler.Proofs.EndToEnd.yulResultsAgreeOn_of_resultsMatch_of_nativeResultsMatchOn - Compiler.Proofs.EndToEnd.nativeIRRuntimeAgreesWithInterpreter_of_ok_agree - Compiler.Proofs.EndToEnd.nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_ok_agree - Compiler.Proofs.EndToEnd.nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_yulHalt_agree - Compiler.Proofs.EndToEnd.nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_yulHalt_project_eq_agree - Compiler.Proofs.EndToEnd.nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_error_agree - Compiler.Proofs.EndToEnd.nativeDispatcherExecAgreesWithInterpreterPositive_of_exec_error_project_eq_agree - Compiler.Proofs.EndToEnd.nativeDispatcherExecAgreesWithInterpreter_of_positive - Compiler.Proofs.EndToEnd.nativeDispatcherExecAgreesWithInterpreter_of_exec_ok_agree - Compiler.Proofs.EndToEnd.nativeDispatcherExecAgreesWithInterpreter_of_exec_yulHalt_agree - Compiler.Proofs.EndToEnd.nativeDispatcherExecAgreesWithInterpreter_of_exec_error_agree - Compiler.Proofs.EndToEnd.nativeDispatcherBlockAgreesWithInterpreter_of_exec_agree - Compiler.Proofs.EndToEnd.nativeCallDispatcherAgreesWithInterpreter_of_dispatcherBlock_agree - Compiler.Proofs.EndToEnd.nativeIRRuntimeAgreesWithInterpreter_of_lowered_callDispatcher_agree - Compiler.Proofs.EndToEnd.layer3_function_preserves_semantics - Compiler.Proofs.EndToEnd.interpretYulRuntime_eq_yulResultOfExec - Compiler.Proofs.EndToEnd.yulStateOfIR_eq_initial - Compiler.Proofs.EndToEnd.execYulStmts_paramState_eq_emptyVars - -- Compiler.Proofs.EndToEnd.internalFunctions_bridged_of_contractWF -- private - Compiler.Proofs.EndToEnd.compileFunctionSpec_bridged_of_safe_static_params - Compiler.Proofs.EndToEnd.compiledExternalFunctions_bridged_of_safe_static - Compiler.Proofs.EndToEnd.yulBody_from_state_eq_yulBody - Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics - Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_via_reference_oracle - Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_evmYulLean_with_function_bridge - Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_evmYulLean - Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_interpreter_bridge - Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_lowered_callDispatcher_bridge - Compiler.Proofs.EndToEnd.layers2_3_ir_matches_yul_via_reference_oracle - Compiler.Proofs.EndToEnd.layers2_3_ir_matches_yul_evmYulLean_with_function_bridge - Compiler.Proofs.EndToEnd.layers2_3_ir_matches_yul_evmYulLean - Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_interpreter_bridge - Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_lowered_callDispatcher_bridge - Compiler.Proofs.EndToEnd.simpleStorage_endToEnd + -- Compiler.Proofs.EndToEnd.sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeResultsMatchOn -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_nativeResultsMatchOn -- private + -- Compiler.Proofs.EndToEnd.txNoWrap_of_calldataSizeFits -- private + -- Compiler.Proofs.EndToEnd.DispatchGuardsSafe.of_payable_of_args_le_of_noWrap -- private + -- Compiler.Proofs.EndToEnd.DispatchGuardsSafe.of_nonpayable_zero_of_args_le_of_noWrap -- private + Compiler.Proofs.EndToEnd.DispatchGuardsSafe.of_value_safe_of_args_le_of_noWrap + Compiler.Proofs.EndToEnd.DispatchGuardsSafe.of_value_safe_of_threshold + -- Compiler.Proofs.EndToEnd.compiledFunctionCalldataThreshold_of_forall₂ -- private + -- Compiler.Proofs.EndToEnd.generatedFunctionCalldataThreshold_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.sourceResultMatchesNativeOn_of_sourceResultMatchesIRResult_of_nativeIRRuntimeMatchesIR -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIROn_of_dispatcherExec -- private + Compiler.Proofs.EndToEnd.nativeResultsMatchOn_interpretIR_of_execIRFunction_guards + Compiler.Proofs.EndToEnd.nativeResultsMatchOn_interpretIR_of_execIRFunction_dispatchGuards + Compiler.Proofs.EndToEnd.nativeResultsMatchOn_interpretIR_revert_of_nonpayable_nonzero + Compiler.Proofs.EndToEnd.nativeResultsMatchOn_interpretIR_revert_of_args_short + Compiler.Proofs.EndToEnd.nativeResultsMatchOn_projectResult_revert_of_nonpayable_nonzero + Compiler.Proofs.EndToEnd.nativeResultsMatchOn_projectResult_revert_of_args_short + -- Compiler.Proofs.EndToEnd.sizeOf_list_ge_length -- private + -- Compiler.Proofs.EndToEnd.sizeOf_buildSwitch_noFallback_noReceive_ge_source_cases_length -- private + -- Compiler.Proofs.EndToEnd.sizeOf_buildSwitch_noFallback_noReceive_ge_source_cases_length_plus24 -- private + -- Compiler.Proofs.EndToEnd.sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length -- private + -- Compiler.Proofs.EndToEnd.sizeOf_emitYul_runtimeCode_noMapping_ge_lowered_cases_length_plus24 -- private + -- Compiler.Proofs.EndToEnd.sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length -- private + -- Compiler.Proofs.EndToEnd.sizeOf_emitYul_runtimeCode_mapping_ge_lowered_cases_length_plus24 -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_positive_match -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_project_eq_match -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_project_eq_match -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_exec_yulHalt_project_eq_match -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_withSwitchIds -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_miss_noFallback_noReceive_withSwitchIds_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_atFuel_artifact -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_error_noFallback_noReceive_withSwitchIds_atFuel_artifact -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_generated_prefix -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_generated_prefix -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_generated_prefix_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_generated_prefix_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_atFuel_forall -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_withSwitchIds_generated_prefix -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_withSwitchIds_generated_prefix -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_payable_withSwitchIds_generated_prefix_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_nonpayable_withSwitchIds_generated_prefix_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeDispatcherExecMatchesIRPositive_of_buildSwitch_selector_hit_ok_noFallback_noReceive_withSwitchIds_atFuel_forall -- private + -- Compiler.Proofs.EndToEnd.compileFunctionSpec_noFuncDefs_of_static_params_and_body -- private + -- Compiler.Proofs.EndToEnd.compileFunctionSpec_noFuncDefs_of_safe_static_params -- private + -- Compiler.Proofs.EndToEnd.compileFunctionSpec_bridged_of_safe_static_params -- private + -- Compiler.Proofs.EndToEnd.compiledExternalFunctions_bridged_of_safe_static -- private + -- Compiler.Proofs.EndToEnd.compiledExternalFunctions_noFuncDefs_of_static_params_and_body -- private + -- Compiler.Proofs.EndToEnd.compiledExternalFunctions_noFuncDefs_of_safe_static -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_generated_dispatcherExec_positive_match -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean -- private + -- Compiler.Proofs.EndToEnd.isStaticScalarParamType_of_supportedExternalParamType -- private + -- Compiler.Proofs.EndToEnd.allStaticScalarParams_of_supportedExternalParams -- private + -- Compiler.Proofs.EndToEnd.generatedRuntimeStaticScalarParams_of_supported -- private + -- Compiler.Proofs.EndToEnd.generatedRuntimeStaticScalarParams_of_supported_except_mapping_writes -- private + -- Compiler.Proofs.EndToEnd.exists_left_of_forall₂_mem_right -- private + -- Compiler.Proofs.EndToEnd.snd_mem_of_mem_zip -- private + -- Compiler.Proofs.EndToEnd.selectorModulus_lt_uint256 -- private + Compiler.Proofs.EndToEnd.generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeFunctionSelectorsSelectorRange_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeFunctionSelectorsRange_of_compile_ok_supported_except_mapping_writes + Compiler.Proofs.EndToEnd.generatedRuntimeFunctionSelectorsSelectorRange_of_compile_ok_supported_except_mapping_writes + -- Compiler.Proofs.EndToEnd.selector_eq_of_find_function_by_selector -- private + Compiler.Proofs.EndToEnd.selectedGeneratedFunctionSelectorRange_of_compile_ok_supported + Compiler.Proofs.EndToEnd.selectedGeneratedFunctionSelectorRange_of_compile_ok_supported_except_mapping_writes + Compiler.Proofs.EndToEnd.generatedRuntimeSupportedStmtList_of_supported + Compiler.Proofs.EndToEnd.supportedFunctionSupportedStmtList_of_supported + -- Compiler.Proofs.EndToEnd.stmtListTouchesUnsupportedStateSurface_append -- private + -- Compiler.Proofs.EndToEnd.stmtListTouchesUnsupportedStateSurfaceExceptMappingWrites_append -- private + -- Compiler.Proofs.EndToEnd.stmtListTouchesUnsupportedEffectSurface_append -- private + Compiler.Proofs.EndToEnd.supportedStmtList_safe_of_state_effect_closed + Compiler.Proofs.EndToEnd.supportedStmtList_safe_of_state_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.generatedRuntimeSafeBodies_of_supported + Compiler.Proofs.EndToEnd.supportedFunctionBody_safe_of_supported + Compiler.Proofs.EndToEnd.supportedFunctionBody_safe_of_supported_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.generatedRuntimeSafeBodies_of_supported_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.generatedConstructorSupportedStmtList_of_supported + Compiler.Proofs.EndToEnd.generatedConstructorSafeBody_of_supported_state_closed + Compiler.Proofs.EndToEnd.generatedConstructorSafeBody_of_supported_state_closed' + Compiler.Proofs.EndToEnd.generatedConstructorSafeBody_of_supported_stmt_safety + Compiler.Proofs.EndToEnd.compileConstructorBody_bridged_of_safe + Compiler.Proofs.EndToEnd.compileConstructorBody_bridged_of_supported_state_closed + Compiler.Proofs.EndToEnd.compileConstructorBody_bridged_of_supported_stmt_safety + Compiler.Proofs.EndToEnd.generatedDeploy_compileConstructor_of_compile_ok_supported + -- Compiler.Proofs.EndToEnd.generatedRuntimePrefixFunctionNamesUnique_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.generatedRuntimePrefixFunctionNamesUnique_of_compile_ok_supported_except_mapping_writes -- private + -- Compiler.Proofs.EndToEnd.generatedRuntimeInternalsAreFuncDefs_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.generatedRuntimeInternalsAreFuncDefs_of_compile_ok_supported_except_mapping_writes -- private + Compiler.Proofs.EndToEnd.generatedRuntimeExternalBodiesBridged_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeExternalBodiesBridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.generatedRuntimeFallbackBodyBridged_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeReceiveBodyBridged_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeFallbackBodyBridged_of_compile_ok_supported_except_mapping_writes + Compiler.Proofs.EndToEnd.generatedRuntimeReceiveBodyBridged_of_compile_ok_supported_except_mapping_writes + -- Compiler.Proofs.EndToEnd.bridgedExpr_dispatch_callvalue -- private + -- Compiler.Proofs.EndToEnd.bridgedExpr_dispatch_calldatasize -- private + -- Compiler.Proofs.EndToEnd.bridgedExpr_dispatch_selector -- private + -- Compiler.Proofs.EndToEnd.bridgedExpr_dispatch_calldatasize_lt -- private + -- Compiler.Proofs.EndToEnd.bridgedExpr_dispatch_has_selector -- private + -- Compiler.Proofs.EndToEnd.bridgedExpr_dispatch_empty_calldata -- private + -- Compiler.Proofs.EndToEnd.bridgedExpr_dispatch_iszero_ident -- private + -- Compiler.Proofs.EndToEnd.callvalueGuard_bridged_local -- private + -- Compiler.Proofs.EndToEnd.calldatasizeGuard_bridged_local -- private + -- Compiler.Proofs.EndToEnd.dispatchBody_bridged_local -- private + -- Compiler.Proofs.EndToEnd.defaultDispatchCase_bridged_local -- private + -- Compiler.Proofs.EndToEnd.switchCases_bridged_local -- private + -- Compiler.Proofs.EndToEnd.buildSwitch_bridged_local -- private + -- Compiler.Proofs.EndToEnd.mappingSlotFuncAt_bridged_local -- private + -- Compiler.Proofs.EndToEnd.runtimeCode_bridged_local -- private + Compiler.Proofs.EndToEnd.switchCaseBody_bridged_of_body + Compiler.Proofs.EndToEnd.generatedRuntimeSwitchCaseBodiesBridged_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeSwitchCaseBodiesBridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.generatedRuntimeSelectedSwitchCaseBodyBridged_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeSelectedFunctionBodyBridged_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeSelectedSwitchCaseBodyBridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.switchCaseBody_noFuncDefs_of_body + Compiler.Proofs.EndToEnd.generatedRuntimeInternalBodiesBridged_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeInternalBodiesBridged_of_compile_ok_supported_except_mapping_writes + Compiler.Proofs.EndToEnd.emitYul_runtimeCode_bridged_of_compile_ok_supported + Compiler.Proofs.EndToEnd.emitYul_runtimeCode_bridged_of_compile_ok_supported_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.generatedRuntimeInternalBodiesHaveNoFuncDefs_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeInternalBodiesHaveNoFuncDefs_of_compile_ok_supported_except_mapping_writes + Compiler.Proofs.EndToEnd.generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_safe + Compiler.Proofs.EndToEnd.generatedRuntimeExternalBodiesHaveNoFuncDefs_of_compile_ok_supported_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.generatedRuntimeSwitchCaseBodiesHaveNoFuncDefs_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeSwitchCaseBodiesHaveNoFuncDefs_of_compile_ok_supported_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.generatedRuntimeSelectedSwitchCaseBodyHasNoFuncDefs_of_compile_ok_supported + Compiler.Proofs.EndToEnd.generatedRuntimeSelectedSwitchCaseBodyHasNoFuncDefs_of_compile_ok_supported_safe + Compiler.Proofs.EndToEnd.generatedRuntimeSelectedSwitchCaseBodyHasNoFuncDefs_of_compile_ok_supported_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.generatedRuntimeNativeFragment_of_compile_ok_supported_safe + Compiler.Proofs.EndToEnd.generatedRuntimeNativeFragment_of_compile_ok_supported_except_mapping_writes_stmt_safety + Compiler.Proofs.EndToEnd.generatedRuntimeNativeFragment_of_compile_ok_supported_safeBodies + Compiler.Proofs.EndToEnd.generatedRuntimeNativeFragment_of_compile_ok_supported + Compiler.Proofs.EndToEnd.validateGeneratedRuntimeNativeFragment_of_compile_ok_supported_safe + Compiler.Proofs.EndToEnd.validateGeneratedRuntimeNativeFragment_of_compile_ok_supported_safeBodies + Compiler.Proofs.EndToEnd.validateGeneratedRuntimeNativeFragment_of_compile_ok_supported + Compiler.Proofs.EndToEnd.validateGeneratedRuntimeNativeFragment_of_compile_ok_supported_except_mapping_writes_stmt_safety + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported_except_mapping_writes_stmt_safety -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_globalDefaults -- private + Compiler.Proofs.EndToEnd.lowerRuntimeContractNative_of_compile_ok_supported_noMapping + -- Compiler.Proofs.EndToEnd.lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher -- private + -- Compiler.Proofs.EndToEnd.lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_public_dispatcher -- private + Compiler.Proofs.EndToEnd.lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved + Compiler.Proofs.EndToEnd.lowerStmtsNative_buildSwitch_noFallback_noReceive_exists_of_compile_ok_supported + Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_exists_of_compile_ok_supported + Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_selectedSwitchCaseBody_exists_of_compile_ok_supported + Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_selectedFunctionBody_exists_of_compile_ok_supported + Compiler.Proofs.EndToEnd.selectedFunctionBodyBridgedAndLowered_of_compile_ok_supported + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_closure_of_compile_ok_supported -- private + Compiler.Proofs.EndToEnd.lowerRuntimeContractNative_of_compile_ok_supported_exists + -- Compiler.Proofs.EndToEnd.lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved -- private + -- Compiler.Proofs.EndToEnd.lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_public_dispatcher_reserved -- private + -- Compiler.Proofs.EndToEnd.lowerRuntimeContractNative_of_compile_ok_supported_ok_public_dispatcher_cases -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNative_buildSwitch_noFallback_noReceive_ok_block -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_buildSwitch_noFallback_noReceive_ok_block -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_match -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_supported -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_eq_match -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_supported -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_positive_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_positive_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_positive_mapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_positive_mapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_project_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_project_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_project_mapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_project_mapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_positive_external_bodies_match -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_external_bodies_match -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_positive_body_closure -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_body_closure -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_supported_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_supported_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_supported_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_supported_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_external_bodies_match -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_external_bodies_match -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_match -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_noMapping_structural -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_miss_noMapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_mapping_structural -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_mapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_miss_mapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_miss_lowered_runtime -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_of_compile_ok_supported -- private + Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_exists_of_compile_ok_supported + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_of_compile_ok_supported -- private + Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_exists_of_compile_ok_supported + Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_exists_of_compile_ok_supported + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_miss_lowered_runtime_selectors_range -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_miss_lowered_runtime_selectors_range_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_structural -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_structural_payable_generated_prefix -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_structural_nonpayable_generated_prefix -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_preserved -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_noMapping_canonical_preserved -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_noMapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_mapping_structural -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_mapping_structural_payable_generated_prefix -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_mapping_structural_nonpayable_generated_prefix -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_lowered_runtime_payable_generated_prefix -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_lowered_runtime_nonpayable_generated_prefix -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_lowered_runtime_payable_generated_prefix_atFuel -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_lowered_runtime_nonpayable_generated_prefix_atFuel -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_noMapping_structural -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_noMapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_mapping_structural -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_mapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_hit_error_matchesIR_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_hit_error_artifact_matchesIR_of_compile_ok_supported -- private + Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_hit_error_matchesIR_exists_of_compile_ok_supported + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_forall_of_compile_ok_supported -- private + Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_exists_of_compile_ok_supported + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHitLoweredArtifacts_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_of_compile_ok_supported -- private + Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_exists_of_compile_ok_supported + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_artifacts_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitBodyHaltExecBridgeAtFuel.of_selected_user_body_halt -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitSuccessBridge.of_body_halt_exec_atFuel -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_halt_exec_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_empty_body_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_empty_body -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_leave_body_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_block_leave_body_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_block_leave -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_block_empty_body_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_block_empty -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_singleton_comment_body_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_singleton_comment -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_stop_body_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_stop_body -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_stop_body -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_preserves -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_exec_bridge -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_selected_user_body_exec_only -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_exec_bridge -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_forall_stmt_write_not_mem -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_nativeStmtsWriteNames_not_mem -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_nativeStmtsWriteNames_not_mem -- private + -- Compiler.Proofs.EndToEnd.nativeStmtsWriteNames_not_mem_of_two_prefix -- private + -- Compiler.Proofs.EndToEnd.nativeStmtsWriteNames_not_mem_of_three_prefix -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_ok_body_eq_of_same_input -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectedUserBodyMatchedFresh_payable_of_caseFresh -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectedUserBodyMatchedFresh_nonpayable_of_caseFresh -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectedUserBodyMatchedFresh_of_switchFresh -- private + -- Compiler.Proofs.EndToEnd.selectedUserBodyClosureAndMatchedFresh_of_compile_ok_supported_switchFresh -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_mappingFreePreservableStraightStmts -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_mappingFreePreservableStraightStmts -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mappingFree -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_bridgedStraightStmts_mapping -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mapping -- private + -- Compiler.Proofs.EndToEnd.NativeBlockPreservesWord_nativeRevertZeroZero -- private + -- Compiler.Proofs.EndToEnd.NativeExprPreservesWord_lowerExprNative_callvalue_any -- private + -- Compiler.Proofs.EndToEnd.NativeExprPreservesWord_lowerExprNative_lt_calldatasize_lit_any -- private + -- Compiler.Proofs.EndToEnd.NativeBlockPreservesWord_switchCaseBody_payable_of_user_body -- private + -- Compiler.Proofs.EndToEnd.NativeBlockPreservesWord_switchCaseBody_nonpayable_of_user_body -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHitBodyPreservesMatched_of_user_body_preserves -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHitBodyPreservesMatched_mappingFree_payable -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHitBodyPreservesMatched_mappingFree_nonpayable -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHitBodyPreservesMatched_mappingFree_of_switchFresh -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHitBodyPreservesMatched_mapping_of_switchFresh -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_and_preserves -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_empty_body -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_empty_body -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_empty_body -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyBridgeAtFuelRevived.of_execIRFunction -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_revived -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_execIRFunction -- private + Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHitBodyPreservesMatched_of_fresh + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitArtifactBridge.of_body_bridge_and_continuation -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_and_continuation -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_atFuel_and_continuation -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_atFuel_restored_and_continuation -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitBridge.of_artifact_bridge -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitBridge.of_success_bridge_and_generated_guard_reverts -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitBridge.of_success_predicate_and_generated_guard_reverts -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitBridge.of_success_predicate_and_generated_guard_reverts_threshold -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_bridge -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_artifact_bridge -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_body_halt_bridge_atFuel -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHit_success_of_user_body_exec_bridge_atFuel_revived_and_continuation -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSelectorHit_success_of_user_body_exec_bridge_atFuel_revived -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitSuccessBridge.of_user_body_exec_bridge_atFuel_revived_and_continuation -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitSuccessBridge.of_user_body_exec_bridge_atFuel_revived -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_mappingFree_switchFresh -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_preserves -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_result -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectorHitSuccessBridge.of_empty_body -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_success_only_atFuel_revived_and_continuation -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_success_only_atFuel_revived -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_empty_selected_body -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_preserves -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree_switchFresh -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedSwitchTempsFreshForNativeBodies_of_case_body_fresh -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree_caseFresh -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_caseFresh -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_stop_body -- private + Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported + Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_body_bridge_and_continuation -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_and_continuation -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_and_continuation -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_restored_and_continuation -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_revived_and_continuation -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_atFuel_revived_and_continuation -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime_selectors_range -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime_source_selectors_range -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_error_lowered_runtime_source_selectors_range_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_preserved -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_mapping_canonical_preserved -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_preserved_lowered_runtime -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime_selectors_range -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime_source_selectors_range -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_lowered_runtime_source_selectors_range_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_selector_hit_ok_mapping_canonical -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical_ofIR_environment_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical_ofIR_globalDefaults_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_mapping_canonical_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_mapping_canonical_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_mapping_canonical_ofIR_environment_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_miss_mapping_canonical_ofIR_globalDefaults_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical_ofIR_environment_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_noMapping_canonical_ofIR_globalDefaults_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical_ofIR_environment_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_error_mapping_canonical_ofIR_globalDefaults_calldata_size_fits -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_preserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_noMapping_canonical_preserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_preserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_selector_hit_ok_mapping_canonical_preserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_match -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_supported_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_supported_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment -- private + -- Compiler.Proofs.EndToEnd.layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults -- private -- Compiler.Proofs.EndToEnd.simpleStorage_functions_bridged -- private - Compiler.Proofs.EndToEnd.simpleStorage_runtimeCode_eq_single_dispatcher - Compiler.Proofs.EndToEnd.lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcher_eq_lowered_stmts - Compiler.Proofs.EndToEnd.lowerStmtsNative_single_block_ok_singleton - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherStmts_lowering_ok - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherStmts_exists_singleton_block - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherStmts_eq_singleton_block - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcher_eq_singleton_block_inner - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_eq_record_inner_block - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec - Compiler.Proofs.EndToEnd.lowerStmtsNative_block_stmts_eq - Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_let_head_eq - Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_if_head_eq - Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_singleton_switch_eq - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_head_let_exists - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_let_if_head_exists - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_let_if_if - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_eq_named_let_if_if_block_exec - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_concrete_let_head - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_if - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton - Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_revert_zero_zero - Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq - Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default_sourceLowered - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_letValue_eq - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if1Cond_eq - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if2Cond_eq - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_exists - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_exists - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_sourceLowered - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if1Body_eq - Compiler.Proofs.EndToEnd.exec_block_simpleStorageNativeDispatcher_if1Body_revert - Compiler.Proofs.EndToEnd.exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_exec - Compiler.Proofs.EndToEnd.exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec - Compiler.Proofs.EndToEnd.exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_exec - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_selectorMiss_revert_via_reduction - Compiler.Proofs.EndToEnd.simpleStorageBuildSwitchSourceCases_map_fst - Compiler.Proofs.EndToEnd.simpleStorageBuildSwitchSourceCases_find?_none - Compiler.Proofs.EndToEnd.simpleStorageBuildSwitchSourceCases_tags_lt_uint256_size - Compiler.Proofs.EndToEnd.simpleStorageBuildSwitchSourceCases_lowered_shape - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredRetrieveCaseBody_head_strip_error - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredRetrieveCaseBodyTail_callvalue_strip_error - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBodyTail2_short_revert - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBodyTail3_halt - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBody_halt - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredRetrieveCaseBodyTail3_closed - Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredRetrieveCaseBody_halt - Compiler.Proofs.EndToEnd.simpleStorageBuildSwitchSourceCases_lowered_concrete - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_selectorMiss_revert - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_error_via_reduction - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_error - Compiler.Proofs.EndToEnd.simpleStorageLoweredHitCasesShape_concrete - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete_tail - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete_tail2 - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error_via_reduction - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail2 - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail3 - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherFuel_ge_25 - Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherFuel_ge_21 - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_selectorMiss_revert_atFuel - Compiler.Proofs.EndToEnd.interpretIR_simpleStorage_selectorMiss - Compiler.Proofs.EndToEnd.interpretIR_simpleStorage_retrieveHit - Compiler.Proofs.EndToEnd.interpretIR_simpleStorage_storeHit_arg - Compiler.Proofs.EndToEnd.interpretIR_simpleStorage_storeHit_short - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_halt_atFuel - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_halt_atFuel - Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_short_revert_atFuel - Compiler.Proofs.EndToEnd.projectStorageFromState_storeHit_initialState_materialized - Compiler.Proofs.EndToEnd.projectResult_retrieveHit_eq - Compiler.Proofs.EndToEnd.simpleStorageNativeRetrieveHitBridge_proved - Compiler.Proofs.EndToEnd.simpleStorageNativeStoreHitBridge_proved - Compiler.Proofs.EndToEnd.simpleStorageNativeSelectorMissBridge_proved - Compiler.Proofs.EndToEnd.simpleStorageNativeCallDispatcherBridge_of_per_case - Compiler.Proofs.EndToEnd.simpleStorage_endToEnd_evmYulLean - Compiler.Proofs.EndToEnd.simpleStorage_endToEnd_native_evmYulLean_of_callDispatcher_bridge + -- Compiler.Proofs.EndToEnd.simpleStorage_functions_loop_free -- private + -- Compiler.Proofs.EndToEnd.simpleStorage_runtimeCode_eq_single_dispatcher -- private + -- Compiler.Proofs.EndToEnd.lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcher_eq_lowered_stmts -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNative_single_block_ok_singleton -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherStmts_lowering_ok -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherStmts_exists_singleton_block -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherStmts_eq_singleton_block -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcher_eq_singleton_block_inner -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_eq_record_inner_block -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_eq_innerBlock_exec -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNative_block_stmts_eq -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_let_head_eq -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_if_head_eq -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_singleton_switch_eq -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_head_let_exists -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_let_if_head_exists -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_let_if_if -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_named_let_if_if -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_eq_named_let_if_if_block_exec -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_concrete_let_head -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_if -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_revert_zero_zero -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq -- private + -- Compiler.Proofs.EndToEnd.lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherInnerStmts_eq_concrete_let_if_switchSingleton_revert_default_sourceLowered -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_letValue_eq -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if1Cond_eq -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if2Cond_eq -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_exists -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_exists -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if2Body_eq_lowerSwitchBlock_revert_default_sourceLowered -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcher_if1Body_eq -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageNativeDispatcher_if1Body_revert -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_exec -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageNativeDispatcherInnerStmts_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_exec -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_eq_lowerNativeSwitchBlock_revert_default_exec_sourceLowered -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_selectorMiss_revert_via_reduction -- private + -- Compiler.Proofs.EndToEnd.simpleStorageBuildSwitchSourceCases_map_fst -- private + -- Compiler.Proofs.EndToEnd.simpleStorageBuildSwitchSourceCases_find?_none -- private + -- Compiler.Proofs.EndToEnd.simpleStorageBuildSwitchSourceCases_tags_lt_uint256_size -- private + -- Compiler.Proofs.EndToEnd.simpleStorageBuildSwitchSourceCases_lowered_shape -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBody_head_strip_error -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredRetrieveCaseBody_head_strip_error -- private + -- Compiler.Proofs.EndToEnd.exec_block_store0_calldataload4_stop_markedPrefix_halt -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBodyTail_callvalue_strip_error -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredRetrieveCaseBodyTail_callvalue_strip_error -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredRetrieveCaseBodyTail2_lt_strip_error -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error -- private + -- Compiler.Proofs.EndToEnd.exec_block_store0_calldataload4_stop_shared_halt -- private + -- Compiler.Proofs.EndToEnd.exec_block_store0_calldataload4_stop_shared_halt_tight -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBodyTail2_lt_strip_error_tight -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBodyTail2_markedPrefix_halt -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBodyTail2_short_revert -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBodyTail3_halt -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredStoreCaseBody_halt -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredRetrieveCaseBodyTail3_closed -- private + -- Compiler.Proofs.EndToEnd.exec_block_loweredLiteralReturnCaseBodyTail_closed -- private + -- Compiler.Proofs.EndToEnd.exec_block_loweredZeroParamLiteralReturnCaseBody_closed -- private + -- Compiler.Proofs.EndToEnd.exec_block_loweredZeroParamSload0ReturnCaseBody_closed -- private + -- Compiler.Proofs.EndToEnd.exec_block_loweredCalldataload4ReturnCaseBodyTail_closed -- private + -- Compiler.Proofs.EndToEnd.exec_block_loweredCalldataloadReturnCaseBodyTail_closed -- private + -- Compiler.Proofs.EndToEnd.exec_block_simpleStorageLoweredRetrieveCaseBody_halt -- private + -- Compiler.Proofs.EndToEnd.simpleStorageBuildSwitchSourceCases_lowered_concrete -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_selectorMiss_revert -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_error_via_reduction -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_error -- private + -- Compiler.Proofs.EndToEnd.simpleStorageLoweredHitCasesShape_concrete -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete_tail -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_error_concrete_tail2 -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error_via_reduction -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail2 -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_error_concrete_tail3 -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherFuel_ge_25 -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeDispatcherFuel_ge_21 -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_selectorMiss_revert_atFuel -- private + -- Compiler.Proofs.EndToEnd.interpretIR_simpleStorage_selectorMiss -- private + -- Compiler.Proofs.EndToEnd.interpretIR_simpleStorage_retrieveHit -- private + -- Compiler.Proofs.EndToEnd.interpretIR_simpleStorage_storeHit_arg -- private + -- Compiler.Proofs.EndToEnd.interpretIR_simpleStorage_storeHit_short -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_retrieveHit_halt_atFuel -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_halt_atFuel -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeContract_dispatcherExec_storeHit_short_revert_atFuel -- private + -- Compiler.Proofs.EndToEnd.projectStorageFromState_storeHit_initialState_materialized -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_store0_calldataload4_stop_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_store0_calldataload4_stop -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_store0_calldataload4_stop -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_store0_calldataload4_stop -- private + -- Compiler.Proofs.EndToEnd.projectResult_retrieveHit_eq -- private + -- Compiler.Proofs.EndToEnd.projectResult_literalReturnHit_eq -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_mstore0_sload0_return32_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.execIRFunction_zeroParam_mstore0_lit_return32 -- private + -- Compiler.Proofs.EndToEnd.execIRFunction_zeroParam_mstore0_sload0_return32 -- private + -- Compiler.Proofs.EndToEnd.execIRFunction_oneParam_store0_value_stop -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_oneParam_store0_value_stop_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_oneParam_store0_value_stop -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_oneParam_store0_value_stop -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_oneParam_store0_value_stop -- private + -- Compiler.Proofs.EndToEnd.selectedCompiledFunction_oneParam_store0_value_stop_shape_of_forall₂ -- private + -- Compiler.Proofs.EndToEnd.selectedGeneratedFunction_oneParam_store0_value_stop_shape_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_oneParam_store0_value_stop -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher_source_oneParam_store0_value_stop -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_mstore0_lit_return32_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_zeroParam_mstore0_lit_return32_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_zeroParam_mstore0_sload0_return32_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.list_getD_eq_of_drop_eq_cons -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_mstore0_calldataload_aligned_return32_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.nativeResultsMatchOn_execIRFunction_mstore0_calldataload4_return32_markedPrefix -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_sload0_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_sload0_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_lit_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_lit_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload4_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload_aligned_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_sload0_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_sload0_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_lit_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_lit_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload4_return32 -- private + -- Compiler.Proofs.EndToEnd.NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload_aligned_return32 -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_sload0_return32 -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_sload0_return32 -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_lit_return32 -- private + -- Compiler.Proofs.EndToEnd.selectedCompiledFunction_zeroParam_lit_return32_shape_of_forall₂ -- private + -- Compiler.Proofs.EndToEnd.selectedGeneratedFunction_zeroParam_lit_return32_shape_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.selectedCompiledFunction_zeroParam_sload0_return32_shape_of_forall₂ -- private + -- Compiler.Proofs.EndToEnd.selectedGeneratedFunction_zeroParam_sload0_return32_shape_of_compile_ok_supported -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_lit_return32 -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_lit_return32 -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_sload0_return32 -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher_source_zeroParam_lit_return32 -- private + -- Compiler.Proofs.EndToEnd.compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher_source_zeroParam_sload0_return32 -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload4_return32 -- private + -- Compiler.Proofs.EndToEnd.nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload_aligned_return32 -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeRetrieveHitMatchBridge_proved -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeStoreHitMatchBridge_proved -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeSelectorMissMatchBridge_proved -- private + -- Compiler.Proofs.EndToEnd.simpleStorageNativeCallDispatcherMatchBridge_of_per_case -- private Compiler.Proofs.EndToEnd.simpleStorage_endToEnd_native_evmYulLean + Compiler.Proofs.EndToEnd.simpleStorage_source_endToEnd_native_evmYulLean_of_sourceIR -- Compiler/Proofs/EventSemantics.lean Compiler.Proofs.EventSemantics.encodeEvents_append @@ -1000,6 +1516,8 @@ end Verity.AxiomAudit -- Compiler.Proofs.IRGeneration.Contract.filterInternalFunctions_eq_nil_of_supported -- private -- Compiler.Proofs.IRGeneration.Contract.filterInternalFunctions_eq_nil_of_supported_except_mapping_writes -- private -- Compiler.Proofs.IRGeneration.Contract.compileValidatedCore_ok_yields_internalFunctions_nil -- private + -- Compiler.Proofs.IRGeneration.Contract.compileValidatedCore_ok_yields_noFallbackEntrypoint -- private + -- Compiler.Proofs.IRGeneration.Contract.compileValidatedCore_ok_yields_noReceiveEntrypoint -- private Compiler.Proofs.IRGeneration.Contract.supported_params_of_supportedSpec Compiler.Proofs.IRGeneration.Contract.supported_params_of_supportedSpec_except_mapping_writes Compiler.Proofs.IRGeneration.Contract.interpretIR_eq_runtimeContractOfFunctions @@ -1008,7 +1526,11 @@ end Verity.AxiomAudit Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_compiled_functions_except_mapping_writes Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_internalFunctions_nil + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_noFallbackEntrypoint + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_noReceiveEntrypoint Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_internalFunctions_nil_except_mapping_writes + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_noFallbackEntrypoint_except_mapping_writes + Compiler.Proofs.IRGeneration.Contract.compile_ok_yields_noReceiveEntrypoint_except_mapping_writes Compiler.Proofs.IRGeneration.Contract.compileFunctionSpec_ok_yields_legacyCompatibleExternalStmtList Compiler.Proofs.IRGeneration.Contract.compileFunctionSpec_ok_yields_legacyCompatibleExternalStmtList_except_mapping_writes -- Compiler.Proofs.IRGeneration.Contract.compiled_functions_legacyCompatibleExternalBodies -- private @@ -1054,6 +1576,22 @@ end Verity.AxiomAudit -- Compiler.Proofs.IRGeneration.ContractFeatureTest.constructorOnly_noConflict -- private -- Compiler.Proofs.IRGeneration.ContractFeatureTest.constructorOnly_compileConstructor -- private + -- Compiler/Proofs/IRGeneration/ContractShape.lean + -- Compiler.Proofs.IRGeneration.ContractShape.pickUniqueFunctionByName_eq_ok_none_of_absent -- private + -- Compiler.Proofs.IRGeneration.ContractShape.compiled_functions_forall₂_of_mapM_ok -- private + -- Compiler.Proofs.IRGeneration.ContractShape.compileValidatedCore_ok_yields_compiled_functions -- private + -- Compiler.Proofs.IRGeneration.ContractShape.filterInternalFunctions_eq_nil_of_all_nonInternal -- private + -- Compiler.Proofs.IRGeneration.ContractShape.filterInternalFunctions_eq_nil_of_supported -- private + -- Compiler.Proofs.IRGeneration.ContractShape.compileValidatedCore_ok_yields_internalFunctions_nil -- private + -- Compiler.Proofs.IRGeneration.ContractShape.compileValidatedCore_ok_yields_deploy_compileConstructor -- private + -- Compiler.Proofs.IRGeneration.ContractShape.compileValidatedCore_ok_yields_noFallbackEntrypoint -- private + -- Compiler.Proofs.IRGeneration.ContractShape.compileValidatedCore_ok_yields_noReceiveEntrypoint -- private + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_compiled_functions + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_internalFunctions_nil + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_deploy_compileConstructor + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noFallbackEntrypoint + Compiler.Proofs.IRGeneration.ContractShape.compile_ok_yields_noReceiveEntrypoint + -- Compiler/Proofs/IRGeneration/Dispatch.lean Compiler.Proofs.IRGeneration.Dispatch.runtimeContractOfFunctions_internalFunctions Compiler.Proofs.IRGeneration.Dispatch.runtimeContractOfFunctions_legacyCompatible @@ -1085,6 +1623,7 @@ end Verity.AxiomAudit Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_of_components Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_params Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_selector + Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_payable Compiler.Proofs.IRGeneration.Function.compileFunctionSpec_ok_components Compiler.Proofs.IRGeneration.Function.compileConstructor_some_ok_of_body Compiler.Proofs.IRGeneration.Function.compileConstructor_ok_components @@ -1522,6 +2061,9 @@ end Verity.AxiomAudit Compiler.Proofs.IRGeneration.FunctionBody.exec_compileStmtList_terminal_core_sizeOf_extraFuel Compiler.Proofs.IRGeneration.FunctionBody.stmtResultToSourceResult_matches_irExecResult + -- Compiler/Proofs/IRGeneration/FunctionShape.lean + Compiler.Proofs.IRGeneration.FunctionShape.compileFunctionSpec_ok_components + -- Compiler/Proofs/IRGeneration/GenericInduction.lean -- Compiler.Proofs.IRGeneration.stmtStepMatchesIRExecWithInternals_of_stmtStepMatchesIRExec -- private Compiler.Proofs.IRGeneration.CompiledStmtStep.withHelpers_of_helperSurfaceClosed @@ -1935,6 +2477,7 @@ end Verity.AxiomAudit Compiler.Proofs.IRGeneration.evalIRCall_tload_singleton Compiler.Proofs.IRGeneration.evalIRCall_mload_singleton Compiler.Proofs.IRGeneration.evalIRCall_calldataload_singleton + Compiler.Proofs.IRGeneration.evalIRCall_sload_singleton -- Compiler.Proofs.IRGeneration.prepareInternalCalleeState_vars -- private Compiler.Proofs.IRGeneration.execIRStmtWithInternals_log0_of_eval_args Compiler.Proofs.IRGeneration.execIRStmtWithInternals_log1_of_eval_args @@ -1949,6 +2492,7 @@ end Verity.AxiomAudit Compiler.Proofs.IRGeneration.execIRStmt_sstore_lit_expr_succ_of_eval Compiler.Proofs.IRGeneration.execIRStmts_sstore_lit_expr_then_stop_succ_succ_succ_of_eval Compiler.Proofs.IRGeneration.execIRStmts_single_stop_succ_succ + Compiler.Proofs.IRGeneration.execIRStmts_single_leave_succ_succ Compiler.Proofs.IRGeneration.execIRStmts_single_block_stop_length_insufficient Compiler.Proofs.IRGeneration.IRState.withTx_sender Compiler.Proofs.IRGeneration.IRState.withTx_storage @@ -1989,6 +2533,9 @@ end Verity.AxiomAudit Compiler.Proofs.IRGeneration.execIRFunctionWithInternals_eq_execIRFunction_of_stmtListCompatibility Compiler.Proofs.IRGeneration.execIRStmtWithInternals_eq_execIRStmt_of_stmtListCompatibility Compiler.Proofs.IRGeneration.interpretIRWithInternalsZeroConservativeExtensionInterfaces_of_stmtCompatibility + Compiler.Proofs.IRGeneration.interpretIR_eq_execIRFunction_of_find?_some_guards + Compiler.Proofs.IRGeneration.interpretIR_eq_revert_of_find?_some_nonpayable_nonzero + Compiler.Proofs.IRGeneration.interpretIR_eq_revert_of_find?_some_args_short Compiler.Proofs.IRGeneration.legacyCompatibleRuntimeDispatch_of_legacyCompatibleRuntimeContract Compiler.Proofs.IRGeneration.interpretIRWithInternalsZeroConservativeExtensionDispatchGoal_of_stmtListCompatibility Compiler.Proofs.IRGeneration.interpretIRWithInternalsZeroConservativeExtensionGoal_of_dispatchGoal @@ -2046,6 +2593,19 @@ end Verity.AxiomAudit Compiler.Proofs.IRGeneration.IRState.setVars_chainId Compiler.Proofs.IRGeneration.IRState.setVars_returnValue Compiler.Proofs.IRGeneration.IRState.setVars_events + -- Compiler.Proofs.IRGeneration.foldl_setParamVars_field_preservation -- private + Compiler.Proofs.IRGeneration.IRState.foldl_setParamVars_storage + Compiler.Proofs.IRGeneration.IRState.foldl_setParamVars_calldata + Compiler.Proofs.IRGeneration.IRState.foldl_setParamVars_returnValue + Compiler.Proofs.IRGeneration.IRState.foldl_setParamVars_events + Compiler.Proofs.IRGeneration.execIRFunction_empty_body + Compiler.Proofs.IRGeneration.execIRFunction_single_stop + Compiler.Proofs.IRGeneration.execIRFunction_store0_calldataload4_stop_of_args_cons + Compiler.Proofs.IRGeneration.execIRFunction_mstore0_calldataload4_return32_of_args_cons + -- Compiler.Proofs.IRGeneration.yulStmtList_length_le_sizeOf -- private + Compiler.Proofs.IRGeneration.execIRFunction_mstore0_calldataload_aligned_return32 + Compiler.Proofs.IRGeneration.execIRFunction_mstore0_sload0_return32 + Compiler.Proofs.IRGeneration.execIRFunction_mstore0_lit_return32 Compiler.Proofs.IRGeneration.prepareInternalCalleeState_storage Compiler.Proofs.IRGeneration.prepareInternalCalleeState_sender Compiler.Proofs.IRGeneration.prepareInternalCalleeState_msgValue @@ -2074,6 +2634,9 @@ end Verity.AxiomAudit Compiler.Proofs.IRGeneration.execIRStmtsWithInternals_of_internalCall_compile Compiler.Proofs.IRGeneration.applyIRTransactionContext_sender Compiler.Proofs.IRGeneration.applyIRTransactionContext_calldata + Compiler.Proofs.IRGeneration.applyIRTransactionContext_storage + Compiler.Proofs.IRGeneration.applyIRTransactionContext_returnValue + Compiler.Proofs.IRGeneration.applyIRTransactionContext_events -- Compiler/Proofs/IRGeneration/IRStorageWord.lean Compiler.Proofs.IRGeneration.IRStorageWord.toNat_ofNat @@ -2319,9 +2882,11 @@ end Verity.AxiomAudit Compiler.Proofs.IRGeneration.SupportedConstructor.paramsSupported Compiler.Proofs.IRGeneration.SupportedFunction.paramNamesNodup Compiler.Proofs.IRGeneration.SupportedFunction.paramsSupported + Compiler.Proofs.IRGeneration.SupportedFunction.paramCalldataThreshold Compiler.Proofs.IRGeneration.SupportedFunction.returnsSupported Compiler.Proofs.IRGeneration.SupportedFunctionExceptMappingWrites.paramNamesNodup Compiler.Proofs.IRGeneration.SupportedFunctionExceptMappingWrites.paramsSupported + Compiler.Proofs.IRGeneration.SupportedFunctionExceptMappingWrites.paramCalldataThreshold Compiler.Proofs.IRGeneration.SupportedFunctionExceptMappingWrites.returnsSupported -- Compiler.Proofs.IRGeneration.exprCompileCore_helperSurfaceClosed -- private -- Compiler.Proofs.IRGeneration.exprCompileCore_internalHelperCallNames_nil -- private @@ -2453,7 +3018,9 @@ end Verity.AxiomAudit Compiler.Proofs.IRGeneration.SupportedSpec.noReceive Compiler.Proofs.IRGeneration.SupportedSpecExceptMappingWrites.noReceive Compiler.Proofs.IRGeneration.SupportedSpec.selectorFunctionParamsSupported + Compiler.Proofs.IRGeneration.SupportedSpec.selectorFunctionParamCalldataThreshold Compiler.Proofs.IRGeneration.SupportedSpecExceptMappingWrites.selectorFunctionParamsSupported + Compiler.Proofs.IRGeneration.SupportedSpecExceptMappingWrites.selectorFunctionParamCalldataThreshold Compiler.Proofs.IRGeneration.SupportedSpec.selectorFunctionParamNamesNodup Compiler.Proofs.IRGeneration.SupportedSpecExceptMappingWrites.selectorFunctionParamNamesNodup Compiler.Proofs.IRGeneration.SupportedSpec.selectorFunctionReturnsSupported @@ -2523,17 +3090,18 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.lowerStmtGroupNativeWithSwitchIds_funcDef Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNativeAux_nil Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNativeAux_funcDef_cons + Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNativeAux_funcDef_cons_empty_of_lowerFunctionDefinition Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNativeAux_stmt_cons Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative_empty -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapterCorrectness.lean - Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.assign_equiv_let - Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.assign_equiv_let' - Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.execYulFuel_stmts_nil - Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.for_init_hoist - Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.for_init_hoist_revert - Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.for_init_hoist_return - Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.for_init_hoist_stop + -- Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.assign_equiv_let -- private + -- Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.assign_equiv_let' -- private + -- Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.legacyExecYulFuel_stmts_nil -- private + -- Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.for_init_hoist -- private + -- Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.for_init_hoist_revert -- private + -- Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.for_init_hoist_return -- private + -- Compiler.Proofs.YulGeneration.Backends.AdapterCorrectness.for_init_hoist_stop -- private -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean Compiler.Proofs.YulGeneration.Backends.isDynamicParamType_false_of_static_scalar @@ -2552,62 +3120,132 @@ end Verity.AxiomAudit -- Compiler.Proofs.YulGeneration.Backends.genParamLoadBodyFrom_calldataload_bridged -- private -- Compiler.Proofs.YulGeneration.Backends.genParamLoadBodyFrom_calldataload_static_scalar_bridged -- private Compiler.Proofs.YulGeneration.Backends.genParamLoads_scalar_bridged + -- Compiler.Proofs.YulGeneration.Backends.genScalarLoad_noFuncDefs -- private + -- Compiler.Proofs.YulGeneration.Backends.genStaticTypeLoads_go_noFuncDefs -- private + -- Compiler.Proofs.YulGeneration.Backends.genStaticTypeLoads_noFuncDefs -- private + -- Compiler.Proofs.YulGeneration.Backends.fixedArrayFirstAlias_noFuncDefs -- private + -- Compiler.Proofs.YulGeneration.Backends.genParamLoadBodyFrom_scalar_noFuncDefs -- private + Compiler.Proofs.YulGeneration.Backends.genParamLoads_scalar_noFuncDefs + -- Compiler.Proofs.YulGeneration.Backends.genSingleParamLoad_static_scalar_noFuncDefs -- private + -- Compiler.Proofs.YulGeneration.Backends.genParamLoadBodyFrom_static_scalar_noFuncDefs -- private + Compiler.Proofs.YulGeneration.Backends.genParamLoads_static_scalar_noFuncDefs Compiler.Proofs.YulGeneration.Backends.genParamLoads_static_scalar_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_binding_leaf_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_binding_leaf_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_binding_leaf_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_binding_leaf_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_pure_binding_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_pure_binding_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_pure_binding_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_pure_binding_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.bridgedSourceStorageStmt_setStorageSingleSlot_of_exprCompileCore Compiler.Proofs.YulGeneration.Backends.compileStmt_setStorage_singleSlot_pure_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStorage_singleSlot_pure_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_storage_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_storage_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_storage_fragment_bridged + -- Compiler.Proofs.YulGeneration.Backends.compileStmtList_noFuncDefs_of_forall -- private + Compiler.Proofs.YulGeneration.Backends.compileStmtList_storage_fragment_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.compileStmt_stop_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_stop_noFuncDefs -- private -- Compiler.Proofs.YulGeneration.Backends.compileStmt_return_external_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_return_external_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_terminator_external_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_terminator_external_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_terminator_external_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_terminator_external_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_return_internal_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_return_internal_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_return_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_return_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_return_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_return_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.revertWithMessage_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.revertWithMessage_chunks_noFuncDefs -- private + -- Compiler.Proofs.YulGeneration.Backends.revertWithMessage_noFuncDefs -- private + Compiler.Proofs.YulGeneration.Backends.bridgedSourceRequireStmt_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSourceRequireStmt_of_guardFamilyClause Compiler.Proofs.YulGeneration.Backends.compileStmt_require_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_require_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_require_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_require_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.compileMappingSlotWrite_singleSlot_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileMappingSlotWrite_singleSlot_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping_singleSlot_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingUint_singleSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping_singleSlot_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingUint_singleSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWrite_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWrite_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWrite_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWrite_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_external_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_external_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_external_body_fragment_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_internal_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_external_body_fragment_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_internal_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_external_structured_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_external_structured_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_structured_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_structured_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_structured_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_structured_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_structured_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_structured_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_external_nested_body_fragment_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_internal_nested_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_external_nested_body_fragment_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_internal_nested_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_external_nested_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_external_nested_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_nested_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_nested_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_nested_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_nested_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_nested_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_nested_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_external_recursive_body_fragment_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_recursive_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_external_recursive_body_fragment_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_recursive_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_recursive_body_fragment_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_recursive_body_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_recursive_body_fragment_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_recursive_body_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_memoryWrite_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_memoryWrite_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_memoryWrite_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_memoryWrite_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_forEach_with_bridged_body + Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_with_noFuncDefs_body + Compiler.Proofs.YulGeneration.Backends.compileStmt_forEach_with_noFuncDefs_body -- Compiler.Proofs.YulGeneration.Backends.sigStores_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.sigStores_noFuncDefs -- private -- Compiler.Proofs.YulGeneration.Backends.revertWithCustomError_zero_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.revertWithCustomError_zero_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_revertError_zero_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_requireError_zero_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_customError_zero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_revertError_zero_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_requireError_zero_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_customError_zero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_customError_zero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_customError_zero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_external_body_with_errors_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_body_with_errors_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_external_body_with_errors_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_body_with_errors_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_body_with_errors_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_body_with_errors_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_body_with_errors_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_body_with_errors_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_external_body_with_errors_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_ite_internal_body_with_errors_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_external_structured_body_with_errors_bridged @@ -2727,127 +3365,289 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.BridgedSourceExternalRecursiveBodyWithErrorsStmt_of_base Compiler.Proofs.YulGeneration.Backends.BridgedSourceInternalRecursiveBodyWithErrorsStmt_of_base Compiler.Proofs.YulGeneration.Backends.compileStmt_rawLog_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_rawLog_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_rawLog_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_rawLog_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_external_body_with_raw_log_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_body_with_raw_log_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_external_body_with_raw_log_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_body_with_raw_log_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_body_with_raw_log_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_body_with_raw_log_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_body_with_raw_log_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_body_with_raw_log_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_external_recursive_body_with_raw_log_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_recursive_body_with_raw_log_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_recursive_body_with_raw_log_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_recursive_body_with_raw_log_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_external_recursive_body_with_raw_log_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_external_recursive_body_with_raw_log_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_internal_recursive_body_with_raw_log_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_internal_recursive_body_with_raw_log_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2_singleSlot_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWrite2_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2_singleSlot_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWrite2_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWrite2_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWrite2_bridged + Compiler.Proofs.YulGeneration.Backends.bridgedSourceStorageAddrStmt_setStorageAddrSingleSlot_of_exprCompileCore Compiler.Proofs.YulGeneration.Backends.compileStmt_setStorageAddr_singleSlot_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_storageAddr_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_storageAddr_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_storageAddr_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_storageAddr_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember_singleSlot_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_structMember_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMember_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember_singleSlot_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_structMember_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMember_noFuncDefs + -- Compiler.Proofs.YulGeneration.Backends.compileMappingSlotWrite_singleSlot_nonzero_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileMappingSlotWrite_singleSlot_nonzero_noFuncDefs -- private + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember_singleSlot_nonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_structMemberNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember_singleSlot_nonzero_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_structMemberNonzero_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMemberNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMemberNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember2_singleSlot_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_structMember2_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMember2_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember2_singleSlot_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_structMember2_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMember2_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember2_singleSlot_nonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_structMember2Nonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember2_singleSlot_nonzero_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_structMember2Nonzero_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMember2Nonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMember2Nonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingWord_singleSlot_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWord_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWord_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingWord_singleSlot_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWord_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWord_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2Word_singleSlot_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_mapping2Word_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_mapping2Word_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2Word_singleSlot_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_mapping2Word_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mapping2Word_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesEmpty_external_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesEmpty_external_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesEmpty_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesEmpty_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_returnValuesEmpty_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_returnValuesEmpty_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesEmpty_internal_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesEmpty_internal_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesEmpty_internal_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesEmpty_internal_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_returnValuesEmpty_internal_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_returnValuesEmpty_internal_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.zip_assigns_bridgedStmts -- private + -- Compiler.Proofs.YulGeneration.Backends.zip_assigns_noFuncDefs -- private -- Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesInternal_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesInternal_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesInternal_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesInternal_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_returnValuesInternal_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_returnValuesInternal_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.zipIdx_mstores_bridgedStmts -- private + -- Compiler.Proofs.YulGeneration.Backends.zipIdx_mstores_noFuncDefs -- private -- Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesExternal_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesExternal_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesExternal_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_returnValuesExternal_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_returnValuesExternal_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_returnValuesExternal_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.bridgedSourceMstoreStmt_of_exprCompileCore -- Compiler.Proofs.YulGeneration.Backends.compileStmt_mstore_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_mstore_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_mstore_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mstore_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mstore_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mstore_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.bridgedSourceTstoreStmt_of_exprCompileCore -- Compiler.Proofs.YulGeneration.Backends.compileStmt_tstore_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_tstore_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_tstore_fragment_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_tstore_fragment_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_tstore_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_tstore_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_storageArrayPush_singleSlot_bridged + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_storageArrayPush_singleSlot_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_storageArrayPush_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_storageArrayPush_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_storageArrayPush_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_storageArrayPush_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_storageArrayPop_singleSlot_bridged + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_storageArrayPop_singleSlot_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_storageArrayPop_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_storageArrayPop_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_storageArrayPop_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_storageArrayPop_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setStorageArrayElement_singleSlot_bridged + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_setStorageArrayElement_singleSlot_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_setStorageArrayElement_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStorageArrayElement_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_setStorageArrayElement_bridged - -- Compiler.Proofs.YulGeneration.Backends.compileMappingSlotWrite_singleSlot_nonzero_bridged -- private + Compiler.Proofs.YulGeneration.Backends.compileStmtList_setStorageArrayElement_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingWord_singleSlot_nonzero_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWordNonzero_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWordNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingWord_singleSlot_nonzero_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWordNonzero_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWordNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2Word_singleSlot_nonzero_bridged Compiler.Proofs.YulGeneration.Backends.compileStmt_mapping2WordNonzero_bridged Compiler.Proofs.YulGeneration.Backends.compileStmtList_mapping2WordNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2Word_singleSlot_nonzero_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmt_mapping2WordNonzero_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mapping2WordNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.bridgedExpr_foldl_mappingSlot Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingChain_singleSlot_bridged + -- Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingChain_singleSlot_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingChain_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingChain_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingChain_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingChain_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmts_multiSlot_sstore_mapping -- private + -- Compiler.Proofs.YulGeneration.Backends.yulStmtsContainFuncDef_multiSlot_sstore_mapping -- private -- Compiler.Proofs.YulGeneration.Backends.compileMappingSlotWrite_multiSlot_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileMappingSlotWrite_multiSlot_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping_multiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping_multiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingUint_multiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingUint_multiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWriteMultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWriteMultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWriteMultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWriteMultiSlot_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmts_multiSlot_sstore_mapping2 -- private + -- Compiler.Proofs.YulGeneration.Backends.yulStmtsContainFuncDef_multiSlot_sstore_mapping2 -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2_multiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2_multiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWrite2MultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWrite2MultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWrite2MultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWrite2MultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember_multiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember_multiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_structMemberMultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_structMemberMultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMemberMultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMemberMultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember2_multiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember2_multiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_structMember2MultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_structMember2MultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMember2MultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMember2MultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingWord_multiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingWord_multiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWordMultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWordMultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWordMultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWordMultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2Word_multiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2Word_multiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mapping2WordMultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mapping2WordMultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mapping2WordMultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mapping2WordMultiSlot_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmts_multiSlot_sstore_mapping_add -- private + -- Compiler.Proofs.YulGeneration.Backends.yulStmtsContainFuncDef_multiSlot_sstore_mapping_add -- private -- Compiler.Proofs.YulGeneration.Backends.compileMappingSlotWrite_multiSlot_nonzero_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.compileMappingSlotWrite_multiSlot_nonzero_noFuncDefs -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingWord_multiSlot_nonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingWord_multiSlot_nonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWordMultiSlotNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingWordMultiSlotNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWordMultiSlotNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingWordMultiSlotNonzero_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmts_multiSlot_sstore_mapping2_add -- private + -- Compiler.Proofs.YulGeneration.Backends.yulStmtsContainFuncDef_multiSlot_sstore_mapping2_add -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2Word_multiSlot_nonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMapping2Word_multiSlot_nonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mapping2WordMultiSlotNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mapping2WordMultiSlotNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mapping2WordMultiSlotNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mapping2WordMultiSlotNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember_multiSlot_nonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember_multiSlot_nonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_structMemberMultiSlotNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_structMemberMultiSlotNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMemberMultiSlotNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMemberMultiSlotNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember2_multiSlot_nonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setStructMember2_multiSlot_nonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_structMember2MultiSlotNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_structMember2MultiSlotNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMember2MultiSlotNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_structMember2MultiSlotNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingPackedWord_singleSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingPackedWord_singleSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingPackedWord_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingPackedWord_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingPackedWord_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingPackedWord_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingPackedWord_singleSlot_nonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingPackedWord_singleSlot_nonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingPackedWordNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingPackedWordNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingPackedWordNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingPackedWordNonzero_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.bridgedStmt_packedInnerBlock_wordOffsetZero -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedStmts_slotsMap_packedInnerBlock_wordOffsetZero -- private + -- Compiler.Proofs.YulGeneration.Backends.yulStmtsContainFuncDef_slotsMap_packedInnerBlock_wordOffsetZero -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingPackedWord_multiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingPackedWord_multiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingPackedWordMultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingPackedWordMultiSlot_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingPackedWordMultiSlot_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingPackedWordMultiSlot_noFuncDefs -- Compiler.Proofs.YulGeneration.Backends.bridgedStmt_packedInnerBlock_wordOffsetNonzero -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedStmts_slotsMap_packedInnerBlock_wordOffsetNonzero -- private + -- Compiler.Proofs.YulGeneration.Backends.yulStmtsContainFuncDef_slotsMap_packedInnerBlock_wordOffsetNonzero -- private Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingPackedWord_multiSlot_nonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_setMappingPackedWord_multiSlot_nonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingPackedWordMultiSlotNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmt_mappingPackedWordMultiSlotNonzero_noFuncDefs Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingPackedWordMultiSlotNonzero_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_mappingPackedWordMultiSlotNonzero_noFuncDefs + -- Compiler.Proofs.YulGeneration.Backends.compileStmtList_append_eq -- private + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_mstoreSingle_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStorageSingleSlot_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStorageAddrSingleSlot_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_requireSingle_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_requireGuardFamilyClause + Compiler.Proofs.YulGeneration.Backends.bridgedSourcePureBindingStmt_letKeccak_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSourcePureBindingStmt_assignKeccak_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_letKeccak_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_assignKeccak_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSourceExternalRecursiveBodyWithRawLogStmts_of_stmtListCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSourceExternalRecursiveBodyWithRawLogStmts_of_stmtListTerminalCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_externalCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_externalTerminalCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_externalMstoreLetKeccak_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_tstoreSingle_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingSingleSlot + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingUintSingleSlot + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingChainSingleSlot + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMapping2SingleSlot + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingWordSingleSlot + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMapping2WordSingleSlot + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingWordSingleSlotNonzero + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMapping2WordSingleSlotNonzero + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setMappingPackedWordSingleSlot + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStructMemberSingleSlot + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStructMember2SingleSlot + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStructMemberSingleSlotNonzero + Compiler.Proofs.YulGeneration.Backends.bridgedSafeStmts_setStructMember2SingleSlotNonzero Compiler.Proofs.YulGeneration.Backends.compileStmtList_always_bridged + Compiler.Proofs.YulGeneration.Backends.compileStmtList_always_noFuncDefs -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean -- Compiler.Proofs.YulGeneration.Backends.word_lt_uint256_size -- private @@ -3061,9 +3861,199 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithBackendContext_evmYulLean_calldataload_bridge Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithBackendContext_evmYulLean_calldatasize_bridge Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithBackendContext_evmYulLean_mappingSlot_bridge - Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithBackendContext_evmYulLean_pure_bridge + -- Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithBackendContext_evmYulLean_pure_bridge -- private + + -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgePredicates.lean + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_nil + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_cons + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_append + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_singleton + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_snoc + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_map_mstore + Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_map_tstore + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_nil + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_append + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_snoc + Compiler.Proofs.YulGeneration.Backends.bridgedExpr_keccak256 + Compiler.Proofs.YulGeneration.Backends.bridgedExpr_mload + Compiler.Proofs.YulGeneration.Backends.bridgedExpr_tload + Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_let_mload + Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_let_tload + Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_let_keccak256 + Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_assign_mload + Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_assign_tload + Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_assign_keccak256 + Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_log_of_bridged_args + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_of_bridgedStraightStmt + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_log_of_bridged_args + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_let_mload + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_let_tload + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_let_keccak256 + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_assign_mload + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_assign_tload + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_assign_keccak256 + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_mstore_of_bridged_args + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_tstore_of_bridged_args + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_sstore_mapping_of_bridged_args + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_sstore_lit_of_bridged_val + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_sstore_ident_of_bridged_val + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_sstore_add_of_bridged_args + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_stop + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_return_of_bridged_args + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_revert + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_leave + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_let_of_bridged_val + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_letMany + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_assign_of_bridged_val + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_comment + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_funcDef + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_of_BridgedStraightStmts + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_straight + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_straight + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_append_straight + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_map_mstore + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_block_of_bridgedStmts + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_block + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_block + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_if_of_bridgedStmts + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_if + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_if + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_for_of_bridgedStmts + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_for + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_for + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_switch_of_bridgedStmts + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_switch + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_switch + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_block_of_bridgedStraightStmts + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_if_of_bridgedStraightStmts + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_for_of_bridgedStraightStmts + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_map_tstore + Compiler.Proofs.YulGeneration.Backends.bridgedStmt_revert_zero + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_revert_zero + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_comment + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_comment + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_let + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_let + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_assign + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_assign + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_letMany + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_letMany + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_stop + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_stop + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_leave + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_leave + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_return + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_return + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_revert + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_revert + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_mstore + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_mstore + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_tstore + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_tstore + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_sstore_lit + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_sstore_lit + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_sstore_ident + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_sstore_ident + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_sstore_mapping + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_sstore_mapping + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_log + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_log + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_funcDef + Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_funcDef -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean + Compiler.Proofs.YulGeneration.Backends.Native.observableSlot_mem_materializedStorageSlots + Compiler.Proofs.YulGeneration.Backends.Native.yulFunctionBodies_nil + Compiler.Proofs.YulGeneration.Backends.Native.yulFunctionBodies_funcDef_cons + Compiler.Proofs.YulGeneration.Backends.Native.yulFunctionBodies_nonFunc_cons + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef_nil + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef_cons + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef_append + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsContainFuncDef_flatMap_false + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtGroupNativeWithSwitchIds_ok_of_yulStmtContainsFuncDef_false + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_ok_of_yulStmtsContainFuncDef_false + Compiler.Proofs.YulGeneration.Backends.Native.lowerSwitchCasesNativeWithSwitchIds_ok_of_yulSwitchCasesContainFuncDef_false + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNative_ok_of_yulStmtsContainFuncDef_false + Compiler.Proofs.YulGeneration.Backends.Native.yulRuntimeTopLevelFunctionNames_nil + Compiler.Proofs.YulGeneration.Backends.Native.yulRuntimeTopLevelFunctionNames_funcDef_cons + Compiler.Proofs.YulGeneration.Backends.Native.yulRuntimeTopLevelFunctionNames_nonFunc_cons + Compiler.Proofs.YulGeneration.Backends.Native.yulRuntimeTopLevelFunctionNames_append + Compiler.Proofs.YulGeneration.Backends.Native.yulRuntimeTopLevelFunctionNames_eq_nil_of_all_nonFunc + Compiler.Proofs.YulGeneration.Backends.Native.yulRuntimeDispatcherStmts_nil + Compiler.Proofs.YulGeneration.Backends.Native.yulRuntimeDispatcherStmts_funcDef_cons + Compiler.Proofs.YulGeneration.Backends.Native.yulRuntimeDispatcherStmts_nonFunc_cons + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeDispatcherHasNoFuncDefs_funcDef_cons + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeDispatcherHasNoFuncDefs_nonFunc_cons + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_funcDef_cons + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_nonFunc_cons + Compiler.Proofs.YulGeneration.Backends.Native.dispatchBody_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchCases_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFuncDefs_noFallback_noReceive + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitchSourceCases_eq_switchCases + Compiler.Proofs.YulGeneration.Backends.Native.find_switch_case_of_find_function + Compiler.Proofs.YulGeneration.Backends.Native.find_switch_case_of_find_function_eq_selector + Compiler.Proofs.YulGeneration.Backends.Native.find_switch_case_of_find_function_none + Compiler.Proofs.YulGeneration.Backends.Native.lowerSwitchCasesNativeWithSwitchIds_find?_some_of_find_function + Compiler.Proofs.YulGeneration.Backends.Native.lowerSwitchCasesNativeWithSwitchIds_find?_none_of_find_function + Compiler.Proofs.YulGeneration.Backends.Native.lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_some_of_find_function + Compiler.Proofs.YulGeneration.Backends.Native.lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNativeAux_single_stmt_eq_lowerStmtsNativeWithSwitchIds + Compiler.Proofs.YulGeneration.Backends.Native.emitYul_runtimeCode_eq_single_dispatcher_of_noMapping_noInternals_noFallback_noReceive + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNative_emitYul_noMapping_noInternals_noFallback_noReceive + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNative_emitYul_noMapping_ok_dispatcher + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNative_single_block_ok_singleton + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNative_block_stmts_eq + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_block_stmts_eq + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_let_head_eq + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_comment_head_eq + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_if_head_eq + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_singleton_switch_eq + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtWriteNames_nativeRevertZeroZeroStmt + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtsWriteNames_singleton_nativeRevertZeroZeroStmt + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForWrites_nil + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForWrites_nativeRevertZeroZeroStmt + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtsWriteNames_payable_dispatch_guard_prefix + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtsWriteNames_nonpayable_dispatch_guard_prefix + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_revert_zero_zero + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_revert_eq + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtsWriteNames_lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_eq_body + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtsWriteNames_lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq_body + -- Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_cons_of_lowerSwitchCasesNativeWithSwitchIds -- private + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_of_lowerSwitchCasesNativeWithSwitchIds + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_buildSwitchSourceCases_of_lowerSwitchCasesNativeWithSwitchIds_of_case_body_fresh + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq + Compiler.Proofs.YulGeneration.Backends.Native.lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered_withSwitchIds + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function_withSwitchIds + Compiler.Proofs.YulGeneration.Backends.Native.buildSwitch_noFallback_noReceive_lowered_inner_find?_none_of_find_function + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeDispatcherHasNoFuncDefs_buildSwitch_noFallback_noReceive + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeDispatcherHasNoFuncDefs_funcDef_prefix_append + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeDispatcherHasNoFuncDefs_runtimeCode_noFallback_noReceive + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeDispatcherHasNoFuncDefs_emitYul_runtimeCode_noFallback_noReceive + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique_append_nonFunc_suffix + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique_buildSwitch_append + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique_runtimeCode + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionNamesUnique_emitYul_runtimeCode + Compiler.Proofs.YulGeneration.Backends.Native.mappingSlotFuncAt_body_noFuncDefs + Compiler.Proofs.YulGeneration.Backends.Native.lowerFunctionDefinitionNativeWithReserved_mappingSlotFuncAt_zero + Compiler.Proofs.YulGeneration.Backends.Native.lowerFunctionDefinitionNativeWithReserved_mappingSlotFuncAt_zero_body + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition_body + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNative_emitYul_mapping_noInternals_noFallback_noReceive_reserved + Compiler.Proofs.YulGeneration.Backends.Native.lowerRuntimeContractNative_emitYul_mapping_ok_dispatcher_reserved + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_append + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_internalFunctions + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_buildSwitch + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_runtimeCode + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs_emitYul_runtimeCode + Compiler.Proofs.YulGeneration.Backends.Native.generatedRuntimeNativeFragment_emitYul_runtimeCode_noFallback_noReceive Compiler.Proofs.YulGeneration.Backends.Native.validateGeneratedRuntimeNativeFragment_ok Compiler.Proofs.YulGeneration.Backends.Native.validateGeneratedRuntimeNativeFragment_error Compiler.Proofs.YulGeneration.Backends.Native.selectorExprMatchesGeneratedDispatcher_selectorExpr @@ -3075,6 +4065,8 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_noChainId_noBlobBaseFee Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_representableBlobBaseFee Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_representableEnvironment + Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_representableEnvironment + Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_ofIR_globalDefaults Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_unsupportedChainId Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_unsupportedBlobBaseFee Compiler.Proofs.YulGeneration.Backends.Native.validateNativeRuntimeEnvironment_unsupportedHeaderBuiltin @@ -3091,12 +4083,14 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataSize -- Compiler.Proofs.YulGeneration.Backends.Native.byteArray_get?_append_left -- private Compiler.Proofs.YulGeneration.Backends.Native.readBytes_zero_get?_of_lt_source + Compiler.Proofs.YulGeneration.Backends.Native.readBytes_get?_of_lt_source Compiler.Proofs.YulGeneration.Backends.Native.readBytes_offset4_get?_of_lt_source Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataReadWord_selectorByte0 Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataReadWord_selectorByte1 Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataReadWord_selectorByte2 Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataReadWord_selectorByte3 Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataReadWord_arg0Byte + Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataReadWord_argByte_of_drop_eq_cons -- Compiler.Proofs.YulGeneration.Backends.Native.byteArray_data_toList_get?_of_get? -- private -- Compiler.Proofs.YulGeneration.Backends.Native.list_reverse_eq_drop4_reverse_append_four -- private Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataReadWord_selectorPrefix @@ -3117,6 +4111,7 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.fromBytes'_selectorPrefix_shift -- Compiler.Proofs.YulGeneration.Backends.Native.usize_sub_toNat_of_le_32 -- private Compiler.Proofs.YulGeneration.Backends.Native.readBytes_zero_32_size + Compiler.Proofs.YulGeneration.Backends.Native.readBytes_32_size Compiler.Proofs.YulGeneration.Backends.Native.readBytes_offset4_32_size Compiler.Proofs.YulGeneration.Backends.Native.readWithPadding_32_size -- Compiler.Proofs.YulGeneration.Backends.Native.byteArray_append_zeroes0 -- private @@ -3131,8 +4126,11 @@ end Verity.AxiomAudit -- Compiler.Proofs.YulGeneration.Backends.Native.list_toByteArray_data_toList -- private Compiler.Proofs.YulGeneration.Backends.Native.uint256_toByteArray_size Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataReadWord_arg0Bytes + Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataReadWord_argBytes_of_drop_eq_cons Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataload4_arg0_value Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataload4_arg0_word + Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataload_aligned_arg_value + Compiler.Proofs.YulGeneration.Backends.Native.initialState_calldataload_aligned_arg_word Compiler.Proofs.YulGeneration.Backends.Native.initialState_selectorExpr_native_value Compiler.Proofs.YulGeneration.Backends.Native.initialState_selectorExpr_native_value_of_readBytes_size Compiler.Proofs.YulGeneration.Backends.Native.initialState_selectorExpr_native_uint256 @@ -3146,52 +4144,132 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.step_iszero_ok Compiler.Proofs.YulGeneration.Backends.Native.step_lt_ok Compiler.Proofs.YulGeneration.Backends.Native.step_calldatasize_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_calldatasize_any Compiler.Proofs.YulGeneration.Backends.Native.step_callvalue_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_callvalue_any Compiler.Proofs.YulGeneration.Backends.Native.step_address_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_address_any Compiler.Proofs.YulGeneration.Backends.Native.step_balance_ok Compiler.Proofs.YulGeneration.Backends.Native.step_origin_ok Compiler.Proofs.YulGeneration.Backends.Native.step_caller_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_caller_any Compiler.Proofs.YulGeneration.Backends.Native.step_timestamp_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_timestamp_any Compiler.Proofs.YulGeneration.Backends.Native.step_number_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_number_any Compiler.Proofs.YulGeneration.Backends.Native.step_chainid_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_chainid_any Compiler.Proofs.YulGeneration.Backends.Native.step_blobbasefee_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_blobbasefee_any Compiler.Proofs.YulGeneration.Backends.Native.step_gasprice_ok Compiler.Proofs.YulGeneration.Backends.Native.step_coinbase_ok Compiler.Proofs.YulGeneration.Backends.Native.step_gaslimit_ok Compiler.Proofs.YulGeneration.Backends.Native.step_selfbalance_ok Compiler.Proofs.YulGeneration.Backends.Native.step_and_ok Compiler.Proofs.YulGeneration.Backends.Native.step_mstore_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_mstore_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mstore_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mstore_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_mstore8_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_mstore8_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mstore8_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mstore8_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_sload_ok Compiler.Proofs.YulGeneration.Backends.Native.step_mload_ok Compiler.Proofs.YulGeneration.Backends.Native.step_keccak256_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_log0_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log0_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log0_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_log0_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_log1_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log1_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log1_pair_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log1_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_log1_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_log2_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log2_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log2_pair_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log2_triple_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log2_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_log2_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_log3_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log3_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log3_pair_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log3_triple_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log3_quad_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log3_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_log3_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_log4_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log4_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log4_pair_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log4_triple_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log4_quad_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log4_quint_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_log4_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_log4_ok Compiler.Proofs.YulGeneration.Backends.Native.step_sstore_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_sstore_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sstore_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sstore_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_tload_ok Compiler.Proofs.YulGeneration.Backends.Native.step_tstore_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_tstore_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_tstore_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_tstore_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_msize_ok Compiler.Proofs.YulGeneration.Backends.Native.step_gas_ok Compiler.Proofs.YulGeneration.Backends.Native.step_returndatasize_ok Compiler.Proofs.YulGeneration.Backends.Native.step_calldatacopy_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_calldatacopy_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_calldatacopy_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_calldatacopy_pair_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_calldatacopy_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_returndatacopy_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_returndatacopy_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_returndatacopy_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_returndatacopy_pair_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_returndatacopy_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_pop_ok Compiler.Proofs.YulGeneration.Backends.Native.step_stop_ok Compiler.Proofs.YulGeneration.Backends.Native.step_return_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_return_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_return_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_return_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.step_revert_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_revert_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_revert_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_revert_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_calldataload_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_calldataload4_initialState_arg0_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_calldataload4_initialState_arg0_ok_withStore Compiler.Proofs.YulGeneration.Backends.Native.primCall_calldataload4_initialState_ofIR_arg0_ok_withStore Compiler.Proofs.YulGeneration.Backends.Native.primCall_shr_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_add_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_add_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_add_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_add_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_sub_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_sub_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sub_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sub_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_mul_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_mul_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mul_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mul_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_div_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_div_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_div_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_div_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_div_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_div_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_div_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_mod_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_mod_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mod_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mod_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_mod_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_mod_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_mod_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_sdiv_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_smod_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_addmod_ok @@ -3200,9 +4278,31 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.primCall_signextend_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_calldataload0_then_shr224_initialState_selector_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_eq_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_eq_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_eq_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_eq_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_eq_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_eq_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_eq_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_iszero_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_iszero_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_iszero_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_iszero_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_iszero_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_lt_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_lt_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_lt_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_lt_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_lt_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_lt_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_lt_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_gt_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_gt_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_gt_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_gt_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_gt_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_gt_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_gt_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_slt_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_sgt_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_calldatasize_ok @@ -3215,6 +4315,14 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.primCall_number_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_chainid_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_blobbasefee_ok + Compiler.Proofs.YulGeneration.Backends.Native.primCall_calldatasize_any_ok + Compiler.Proofs.YulGeneration.Backends.Native.primCall_callvalue_any_ok + Compiler.Proofs.YulGeneration.Backends.Native.primCall_address_any_ok + Compiler.Proofs.YulGeneration.Backends.Native.primCall_caller_any_ok + Compiler.Proofs.YulGeneration.Backends.Native.primCall_timestamp_any_ok + Compiler.Proofs.YulGeneration.Backends.Native.primCall_number_any_ok + Compiler.Proofs.YulGeneration.Backends.Native.primCall_chainid_any_ok + Compiler.Proofs.YulGeneration.Backends.Native.primCall_blobbasefee_any_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_gasprice_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_coinbase_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_gaslimit_ok @@ -3223,14 +4331,83 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.primCall_or_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_xor_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_not_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_not_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_not_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_not_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_not_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_shl_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_byte_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_sar_ok + Compiler.Proofs.YulGeneration.Backends.Native.step_sdiv_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sdiv_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sdiv_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_smod_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_smod_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_smod_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_exp_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_exp_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_exp_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_signextend_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_signextend_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_signextend_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_slt_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_slt_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_slt_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sgt_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sgt_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sgt_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_and_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_and_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_and_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_or_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_or_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_or_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_xor_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_xor_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_xor_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_shl_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_shl_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_shl_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_shr_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_shr_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_shr_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_byte_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_byte_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_byte_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sar_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sar_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sar_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sload_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_sload_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_calldataload_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_calldataload_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mload_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mload_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_tload_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_tload_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_keccak256_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_keccak256_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_keccak256_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_addmod_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_addmod_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_addmod_pair_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_addmod_overarity_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mulmod_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mulmod_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mulmod_pair_invalid + Compiler.Proofs.YulGeneration.Backends.Native.step_mulmod_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_mstore_ok + Compiler.Proofs.YulGeneration.Backends.Native.primCall_mstore_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_mstore_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_mstore_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_mstore8_ok + Compiler.Proofs.YulGeneration.Backends.Native.primCall_mstore8_nil_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_mstore8_singleton_invalid + Compiler.Proofs.YulGeneration.Backends.Native.primCall_mstore8_overarity_invalid Compiler.Proofs.YulGeneration.Backends.Native.primCall_sload_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_mload_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_keccak256_ok + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition_exec_revivable Compiler.Proofs.YulGeneration.Backends.Native.primCall_log0_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_log1_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_log2_ok @@ -3264,6 +4441,8 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.eval_lowerExprNative_lt_calldatasize_ok_fuel Compiler.Proofs.YulGeneration.Backends.Native.eval_lowerExprNative_sload_ok_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerExprNative_mstore_lit_sload_lit_ok_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerExprNative_mstore_lit_lit_ok_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerExprNative_mstore_lit_calldataload_lit_ok_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerExprNative_return_lit_lit_error_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_block_singleton_lowerExprNative_return_lit_lit_error_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_let_lowerExprNative_iszero_lt_calldatasize_4_ok @@ -3284,6 +4463,12 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.exec_block_append_error Compiler.Proofs.YulGeneration.Backends.Native.exec_block_append_prefix_error Compiler.Proofs.YulGeneration.Backends.Native.exec_block_nil_ok + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_nil_ok_add_ten + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_leave_ok_add_ten + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_block_leave_ok_add_ten + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_block_nil_ok_add_ten + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_stop_halt_add_ten + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_noop_block_head_eq Compiler.Proofs.YulGeneration.Backends.Native.exec_nativeSwitchPrefix_selector_initialState_ok Compiler.Proofs.YulGeneration.Backends.Native.exec_nativeSwitchPrefix_selector_initialState_ok_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_nativeSwitchPrefix_selector_initialState_store_ok_fuel @@ -3292,8 +4477,14 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.exec_if_eval_nonzero_error Compiler.Proofs.YulGeneration.Backends.Native.exec_if_lowerExprNative_iszero_ident_one_skip Compiler.Proofs.YulGeneration.Backends.Native.exec_if_lowerExprNative_callvalue_skip_zero_fuel + Compiler.Proofs.YulGeneration.Backends.Native.natToUInt256_eq_zero_of_mod_evm + Compiler.Proofs.YulGeneration.Backends.Native.natToUInt256_ne_zero_of_mod_ne + Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_msgValue_zero_mod_of_nonpayable + Compiler.Proofs.YulGeneration.Backends.Native.DispatchGuardsSafe_calldata_threshold_lt -- Compiler.Proofs.YulGeneration.Backends.Native.uint256_lt_ofNat_eq_zero_of_ge -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.uint256_lt_ofNat_eq_one_of_lt -- private Compiler.Proofs.YulGeneration.Backends.Native.exec_if_lowerExprNative_lt_calldatasize_skip_ge_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_if_lowerExprNative_lt_calldatasize_take_lt_revert_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_if_lowerExprNative_iszero_ident_one_skip_fuel -- Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState_insert_lookup_self -- private Compiler.Proofs.YulGeneration.Backends.Native.exec_if_lowerExprNative_ident_one_take_fuel @@ -3332,6 +4523,7 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.lowerNativeSwitchBlock_selectorExpr_eq_nativeSwitchParts Compiler.Proofs.YulGeneration.Backends.Native.state_lookup_insert_of_ne Compiler.Proofs.YulGeneration.Backends.Native.state_getElem_insert_of_ne + Compiler.Proofs.YulGeneration.Backends.Native.state_getElem_insert_self_ok Compiler.Proofs.YulGeneration.Backends.Native.state_getElem_multifill_of_not_mem Compiler.Proofs.YulGeneration.Backends.Native.state_getElem_foldr_insert_zero_of_not_mem Compiler.Proofs.YulGeneration.Backends.Native.state_getElem_setSharedState @@ -3340,70 +4532,126 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.state_getElem_setStore_ok_left Compiler.Proofs.YulGeneration.Backends.Native.state_getElem_setStore_ok Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_calldatasize + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_calldatasize_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_callvalue + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_callvalue_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_address + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_address_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_balance Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_origin Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_caller + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_caller_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_timestamp + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_timestamp_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_number + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_number_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_chainid + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_chainid_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_blobbasefee + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_blobbasefee_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_gasprice Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_coinbase Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_gaslimit Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_selfbalance Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_unary_same_state + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_unary_same_state_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_binary_same_state Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_ternary_same_state + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_binary_same_state_values + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_ternary_same_state_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_iszero + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_iszero_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_shr + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_shr_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_add + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_add_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sub + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sub_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mul + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mul_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_div + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_div_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mod + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mod_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sdiv + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sdiv_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_smod + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_smod_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_addmod + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_addmod_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mulmod + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mulmod_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_exp + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_exp_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_signextend + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_signextend_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_eq + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_eq_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_lt + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_lt_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_gt + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_gt_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_slt + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_slt_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sgt + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sgt_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_and + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_and_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_or + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_or_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_xor + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_xor_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_not + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_not_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_shl + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_shl_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_byte + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_byte_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sar + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sar_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sload + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sload_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_calldataload + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_calldataload_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mload + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mload_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mstore + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mstore_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mstore8 + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_mstore8_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_tload + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_tload_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_tstore + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_tstore_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sstore + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_sstore_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_stop Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_return Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_revert + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_return_values + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_revert_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_msize Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_gas Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_returndatasize Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_calldatacopy Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_returndatacopy + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_calldatacopy_values + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_returndatacopy_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_pop Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_keccak256 + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_keccak256_values Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_log0 Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_log1 Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_log2 Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_log3 Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_log4 + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_noop_result + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_log0_values + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_log1_values + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_log2_values + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_log3_values + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_log4_values + Compiler.Proofs.YulGeneration.Backends.Native.NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_var Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lit Compiler.Proofs.YulGeneration.Backends.Native.NativeEvalArgsPreservesWord_nil @@ -3415,11 +4663,26 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_str Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_ident Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_call_prim_of_evalArgs_primCall_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_call_prim_of_nativeEvalArgs_primCall_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_call_user_of_evalArgs_call_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_call_user_of_nativeEvalArgs_call_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_call_userFunction_of_evalArgs_call_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves Compiler.Proofs.YulGeneration.Backends.Native.state_getElem_overwrite?_left Compiler.Proofs.YulGeneration.Backends.Native.state_getElem_restoreCallFrame_of_ok + Compiler.Proofs.YulGeneration.Backends.Native.native_call_preserves_lookup_of_revivable_body + Compiler.Proofs.YulGeneration.Backends.Native.nativeMappingSlotFunctionDefinition_exec_revivable_of_ok_state + Compiler.Proofs.YulGeneration.Backends.Native.state_foldr_insert_ok_exists + Compiler.Proofs.YulGeneration.Backends.Native.state_mkOk_initcall_ok_exists + Compiler.Proofs.YulGeneration.Backends.Native.native_mappingSlot_call_preserves_lookup + Compiler.Proofs.YulGeneration.Backends.Native.native_mappingSlot_call_preserves_lookup_state + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_mappingSlot_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_of_bridgedExpr_mappingContract + Compiler.Proofs.YulGeneration.Backends.Native.NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_bridgedExprs_mappingContract + Compiler.Proofs.YulGeneration.Backends.Native.NativeExprPreservesWord_lowerExprNative_of_mappingFreeBridgedExpr + Compiler.Proofs.YulGeneration.Backends.Native.NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchDiscrTempName_ne_matchedTempName Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchPrefixFinalState_matched Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchPrefixFinalState_discr @@ -3431,6 +4694,13 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_forall_stmt Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_of_forall_stmt_write_not_mem Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtWriteNames_not_mem_of_nativeStmtsWriteNames_not_mem + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtWriteNames_let_singleton_not_mem_ne + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtWriteNames_let_not_mem_vars + Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtWriteNames_lowerAssignNative_not_mem_ne + Compiler.Proofs.YulGeneration.Backends.Native.collectYulStmtWriteNames_append + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsWriteNames_append + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtsWriteNames_cons + Compiler.Proofs.YulGeneration.Backends.Native.yulStmtWriteNames_not_mem_of_yulStmtsWriteNames_not_mem Compiler.Proofs.YulGeneration.Backends.Native.collectNativeStmtWriteNames_append Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtsWriteNames_append Compiler.Proofs.YulGeneration.Backends.Native.nativeStmtsWriteNames_cons @@ -3452,6 +4722,12 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_if_of_eval_preserves_and_nativeStmtsWriteNames_not_mem Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_if_of_cond_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_if_of_cond_preserves_and_nativeStmtsWriteNames_not_mem + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchBranchFold_ok_preserves_word + Compiler.Proofs.YulGeneration.Backends.Native.execSwitchCases_ok_branch_preserves_word + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_switch_of_eval_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_switch_of_cond_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_switch_of_cond_preserves_and_nativeStmtsWriteNames_not_mem + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_switch_of_eval_preserves_and_nativeStmtsWriteNames_not_mem Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerAssignNative_lit_of_ne Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerAssignNative_hex_of_ne Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerAssignNative_ident_of_ne @@ -3465,48 +4741,162 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_lowerExprNative_ident_of_not_mem Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_prim_of_evalArgs_primCall_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_user_of_evalArgs_call_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_prim_of_nativeEvalArgs_primCall_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_user_of_nativeEvalArgs_call_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_lowerExprNative_call_userFunction_of_evalArgs_call_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_lowerExprNative_mappingSlot_of_nativeEvalArgs Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerAssignNative_call_runtimePrimOp_of_evalArgs_primCall_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerAssignNative_call_userFunction_of_evalArgs_call_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerAssignNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerAssignNative_call_userFunction_of_nativeEvalArgs_call_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_lowerExprNative_of_mappingFreeBridgedExpr + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_letMany_lowerExprNative_of_mappingFreeBridgedExpr + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerAssignNative_of_mappingFreeBridgedExpr + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerAssignNative_mappingSlot_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_let_lowerExprNative_of_bridgedExpr_mappingContract + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_letMany_lowerExprNative_of_bridgedExpr_mappingContract + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerAssignNative_of_bridgedExpr_mappingContract + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_empty_block + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_comment + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_let + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_let_of_write_not_mem + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_letMany_of_write_not_mem + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_assign + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_assign_of_write_not_mem Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_prim_of_evalArgs_primCall_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_user_of_evalArgs_call_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_user_of_nativeEvalArgs_call_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_userFunction_of_evalArgs_call_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mappingSlot_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_call_of_bridgedExpr_mappingContract Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_mstore_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_mstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_mstore_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_mstore8_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_mstore8_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_mstore8_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_sstore_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_sstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_sstore_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_tstore_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_tstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_tstore_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log0_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log0_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log1_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log1_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log2_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log2_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log3_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log3_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log4_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log4_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log0_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log1_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log2_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log3_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_log4_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_return_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_return_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_return_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_revert_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_revert_of_nativeEvalArgs_and_evalArgs_shape_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_evalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_nativeEvalArgs_and_evalArgs_shape_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_revert_of_nativeEvalArgs_preserves + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_nativeEvalArgs_preserves Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_stop Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_exprStmtCall_lowerExprNative_stop + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_stop + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log0 + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log1 + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log2 + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log3 + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log4 + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log0_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log1_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log2_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log3_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_log4_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_mstore + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_mstore_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_mstore8 + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_mstore8_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_sstore + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_sstore_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_tstore + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_tstore_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_return + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_return_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_revert + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_revert_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_calldatacopy + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_returndatacopy + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_calldatacopy_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_expr_returndatacopy_of_nativeEvalArgs + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreeBridgedExpr.of_bridgedExpr + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreePreservableStraightStmt.of_bridgedStraightStmt + Compiler.Proofs.YulGeneration.Backends.Native.NativeMappingFreePreservableStraightStmts.of_bridgedStraightStmts + -- Compiler.Proofs.YulGeneration.Backends.Native.bridgedExpr_mappingSlot_of_bridged -- private + Compiler.Proofs.YulGeneration.Backends.Native.NativePreservableStraightStmt.of_bridgedStraightStmt + Compiler.Proofs.YulGeneration.Backends.Native.NativePreservableStraightStmts.of_bridgedStraightStmts + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_of_mappingFreePreservableStraightStmt + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_of_mem_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_of_nativePreservableStraightStmt + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_of_mem_lowerStmtsNativeWithSwitchIds_of_nativePreservableStraightStmts + Compiler.Proofs.YulGeneration.Backends.Native.NativeStmtPreservesWord_of_mem_lowerStmtsNativeWithSwitchIds_of_bridgedStraightStmts + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_nativePreservableStraightStmts + Compiler.Proofs.YulGeneration.Backends.Native.NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_bridgedStraightStmts Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_case_matched_not_mem Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_case_discr_not_mem Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchTempsFreshForNativeBodies_find_hit_matched_not_mem @@ -3563,11 +4953,27 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_none_with_default_nonempty_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_storePrefix_tail_error_fuel + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId_reviveJump_eq + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId_weiValue + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId_calldata_size + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId_matched + Compiler.Proofs.YulGeneration.Backends.Native.exec_if_callvalue_skip_markedPrefix_zero_mod_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_if_callvalue_take_markedPrefix_nonzero_revert_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_if_lt_calldatasize_skip_markedPrefix_ge_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_if_lt_calldatasize_take_markedPrefix_lt_revert_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_payable_prefix_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_payable_calldata_revert_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_nonpayable_prefix_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_nonpayable_callvalue_revert_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_nonpayable_calldata_revert_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_payable_lowered_prefix_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_switchCaseBody_nonpayable_lowered_prefix_eq Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchInitialOkState_insert_hasSelector_eq Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchPrefixStoreState_matched_eq Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchPrefixStoreState_discr_eq Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_storePrefix_tail_ok_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_preserved_store_fuel + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_finalMatched_store_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_fresh_store_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_fuel Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_error_store_fuel @@ -3580,6 +4986,8 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState_missingAccountStorageSlot Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState_missingAccount Compiler.Proofs.YulGeneration.Backends.Native.initialState_observableStorageSlot + Compiler.Proofs.YulGeneration.Backends.Native.initialState_materializedStorageSlot + Compiler.Proofs.YulGeneration.Backends.Native.nativeSwitchStoreMarkedPrefixStateForId_materializedStorageSlot Compiler.Proofs.YulGeneration.Backends.Native.initialState_sload_observableSlot_value Compiler.Proofs.YulGeneration.Backends.Native.initialState_sload_materializedSlot_value Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState_retrieveHit_initialState_materialized @@ -3609,6 +5017,10 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.byteArrayWord_uint256_toByteArray Compiler.Proofs.YulGeneration.Backends.Native.projectLogEntry_topicsAndWordData Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState_logSeries + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState_initialState + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState_nativeSwitchStoreMarkedPrefixStateForId + Compiler.Proofs.YulGeneration.Backends.Native.projectStorageFromState_setStore_ok_left + Compiler.Proofs.YulGeneration.Backends.Native.projectLogsFromState_setStore_ok_left Compiler.Proofs.YulGeneration.Backends.Native.projectHaltReturn_stop Compiler.Proofs.YulGeneration.Backends.Native.projectHaltReturn_32ByteReturn Compiler.Proofs.YulGeneration.Backends.Native.projectHaltReturn_non32ByteReturn @@ -3620,6 +5032,13 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.callDispatcher_zero Compiler.Proofs.YulGeneration.Backends.Native.callDispatcher_succ_eq_callDispatcherBlockResult Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_success + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_returnValue + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_events + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_storageSlot + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_nativeSwitchStoreMarkedPrefixStateForId_observableStorageSlot + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_setStore_ok_left + Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_restoreCallFrame_of_reviveJump_ok Compiler.Proofs.YulGeneration.Backends.Native.primCall_sstore_initialState_wordSlot_withStore_projectResult_eq Compiler.Proofs.YulGeneration.Backends.Native.projectResult_yulHalt Compiler.Proofs.YulGeneration.Backends.Native.projectResult_ok_events @@ -3682,29 +5101,176 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.Native.projectResult_hardError_finalStorageSlot Compiler.Proofs.YulGeneration.Backends.Native.projectResult_hardError_finalMappings Compiler.Proofs.YulGeneration.Backends.Native.projectResult_hardError_events + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq_payable_generated_prefix + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq_nonpayable_generated_prefix + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq_payable_generated_prefix + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq_nonpayable_generated_prefix + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq_payable_generated_prefix + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq_nonpayable_generated_prefix + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_preserved + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_payable_generated_prefix + Compiler.Proofs.YulGeneration.Backends.Native.exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq_nonpayable_generated_prefix + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult + Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_peel + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_payable_generated_prefix_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_nonpayable_generated_prefix_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_callvalue_revert_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_callvalue_revert_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_payable_args_short_revert_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_args_short_revert_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_payable_args_short_revert_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_args_short_revert_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_callvalue_revert_withSwitchIds_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_payable_args_short_revert_withSwitchIds_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_nonpayable_args_short_revert_withSwitchIds_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_generated_prefix_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_generated_prefix_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_withSwitchIds_generated_prefix_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_withSwitchIds_generated_prefix_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_generated_prefix_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_generated_prefix_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_payable_withSwitchIds_generated_prefix_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_nonpayable_withSwitchIds_generated_prefix_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_atFuel_artifact_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_projectResult_eq_preserved + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_atFuel_projectResult_eq_preserved + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_atFuel_projectResult_eq_preserved_forall + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_error_withSwitchIds_atFuel_artifact_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_projectResult_eq_preserved + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_atFuel_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_atFuel_projectResult_eq_preserved + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_some_ok_withSwitchIds_atFuel_projectResult_eq_preserved_forall + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_withSwitchIds_projectResult_eq + Compiler.Proofs.YulGeneration.Backends.Native.contractDispatcherExecResult_buildSwitch_noFallback_noReceive_selector_find_none_withSwitchIds_atFuel_projectResult_eq -- Compiler.Proofs.YulGeneration.Backends.Native.simpleStorageSelectors_tagsRange -- private - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_find_none_with_revert_default_projectResult - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_find_none_with_revert_default_projectResult_eq - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_tx_find_none_with_revert_default_projectResult_eq - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_tx_miss_with_revert_default_projectResult_eq - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageConcrete_tx_miss_with_revert_default_projectResult_eq - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_fuel - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_store_fuel - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_projectResult_eq - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageConcrete_store_hit_projectResult_eq - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_error_fuel - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_projectResult_eq - Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageConcrete_retrieve_hit_projectResult_eq + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_find_none_with_revert_default_projectResult -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_find_none_with_revert_default_projectResult_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_tx_find_none_with_revert_default_projectResult_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_tx_miss_with_revert_default_projectResult_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageConcrete_tx_miss_with_revert_default_projectResult_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_fuel -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_error_store_fuel -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_store_hit_projectResult_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageConcrete_store_hit_projectResult_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_error_fuel -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageSelectors_retrieve_hit_projectResult_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.Native.exec_lowerNativeSwitchBlock_simpleStorageConcrete_retrieve_hit_projectResult_eq -- private Compiler.Proofs.YulGeneration.Backends.Native.projectResult_finalMappings Compiler.Proofs.YulGeneration.Backends.Native.interpretRuntimeNative_loweringError Compiler.Proofs.YulGeneration.Backends.Native.interpretRuntimeNative_generatedFragmentError Compiler.Proofs.YulGeneration.Backends.Native.interpretRuntimeNative_eq_callDispatcher_of_lowerRuntimeContractNative + Compiler.Proofs.YulGeneration.Backends.Native.interpretRuntimeNative_succ_eq_contractDispatcherBlockResult_of_lowerRuntimeContractNative + Compiler.Proofs.YulGeneration.Backends.Native.interpretRuntimeNative_succ_eq_contractDispatcherExecResult_of_lowerRuntimeContractNative Compiler.Proofs.YulGeneration.Backends.Native.interpretRuntimeNative_environmentError Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative_eq_interpretRuntimeNative Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative_loweringError Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative_generatedFragmentError Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative_eq_callDispatcher_of_lowerRuntimeContractNative + Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative_succ_eq_contractDispatcherBlockResult_of_lowerRuntimeContractNative + Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative_succ_eq_contractDispatcherExecResult_of_lowerRuntimeContractNative + + -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeSignedArithLemmas.lean + -- Compiler.Proofs.YulGeneration.Backends.fin_val_mul_neg1 -- private + -- Compiler.Proofs.YulGeneration.Backends.natAbs_ofNat_sub -- private + Compiler.Proofs.YulGeneration.Backends.int256_div_toUint256_val_eq_uint256_sdiv + -- Compiler.Proofs.YulGeneration.Backends.eq0_true_of_val_eq_zero -- private + -- Compiler.Proofs.YulGeneration.Backends.eq0_false_of_val_ne_zero -- private + -- Compiler.Proofs.YulGeneration.Backends.int256_ofInt_nat_toUint256_val -- private + -- Compiler.Proofs.YulGeneration.Backends.int256_ofInt_neg_nat_toUint256_val -- private + -- Compiler.Proofs.YulGeneration.Backends.int256_ofUint256_coe_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.evmModulus_eq_specModulus -- private + -- Compiler.Proofs.YulGeneration.Backends.int256_modulus_eq_specModulus -- private + -- Compiler.Proofs.YulGeneration.Backends.signedAbsNat_of_ofUint256 -- private + -- Compiler.Proofs.YulGeneration.Backends.int256_coe_lt_zero_iff -- private + -- Compiler.Proofs.YulGeneration.Backends.int256_coe_eq_zero_iff -- private + -- Compiler.Proofs.YulGeneration.Backends.int256_mod_toUint256_val_eq_smodSpec -- private + -- Compiler.Proofs.YulGeneration.Backends.uint256_abs_toNat_eq_specAbs -- private + -- Compiler.Proofs.YulGeneration.Backends.uint256_mod_toNat_of_nonzero -- private + -- Compiler.Proofs.YulGeneration.Backends.uint256_toSigned_ofNat_toNat_of_lt -- private + -- Compiler.Proofs.YulGeneration.Backends.uint256_toSigned_negSucc_toNat_of_lt -- private + -- Compiler.Proofs.YulGeneration.Backends.uint256_smod_toNat_eq_smodSpec -- private + Compiler.Proofs.YulGeneration.Backends.int256_mod_toUint256_val_eq_uint256_smod + -- Compiler.Proofs.YulGeneration.Backends.uint256_lt_zero_false -- private + -- Compiler.Proofs.YulGeneration.Backends.uint256_complement_val -- private + -- Compiler.Proofs.YulGeneration.Backends.uint256_complement_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.uint256_shiftRight_val -- private + -- Compiler.Proofs.YulGeneration.Backends.uint256_sar_toNat_eq_sarSpec -- private + -- Compiler.Proofs.YulGeneration.Backends.int_two_pow_eq_nat -- private + -- Compiler.Proofs.YulGeneration.Backends.int_fdiv_ofNat_two_pow -- private + -- Compiler.Proofs.YulGeneration.Backends.int_sub_modulus_eq_negSucc -- private + -- Compiler.Proofs.YulGeneration.Backends.int_fdiv_neg_raw_two_pow -- private + -- Compiler.Proofs.YulGeneration.Backends.int256_ofInt_negSucc_toUint256_val -- private + -- Compiler.Proofs.YulGeneration.Backends.int256_sar_toUint256_val_eq_sarSpec -- private + Compiler.Proofs.YulGeneration.Backends.int256_sar_toUint256_val_eq_uint256_sar + -- Compiler.Proofs.YulGeneration.Backends.se_uint256_eq_of_val -- private + -- Compiler.Proofs.YulGeneration.Backends.se_lor_val -- private + -- Compiler.Proofs.YulGeneration.Backends.se_land_val -- private + -- Compiler.Proofs.YulGeneration.Backends.se_sub_val -- private + -- Compiler.Proofs.YulGeneration.Backends.se_tb_pow_sub_pow -- private + -- Compiler.Proofs.YulGeneration.Backends.se_tb_ne_zero -- private + -- Compiler.Proofs.YulGeneration.Backends.se_tb_eq_zero -- private + -- Compiler.Proofs.YulGeneration.Backends.se_set_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.se_clear_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.se_tb_val -- private + -- Compiler.Proofs.YulGeneration.Backends.se_shiftLeft_one_val -- private + -- Compiler.Proofs.YulGeneration.Backends.se_val_val_of_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.se_sign_set -- private + -- Compiler.Proofs.YulGeneration.Backends.se_sign_clear -- private + -- Compiler.Proofs.YulGeneration.Backends.se_nat_to_sign -- private + -- Compiler.Proofs.YulGeneration.Backends.se_verity_ofNat -- private + -- Compiler.Proofs.YulGeneration.Backends.se_size_to_uint256_val -- private + Compiler.Proofs.YulGeneration.Backends.uint256_signextend_val_eq_uint256_signextend + + -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanPureBuiltinLemmas.lean + -- Compiler.Proofs.YulGeneration.Backends.uint256_size_eq_evmModulus -- private + -- Compiler.Proofs.YulGeneration.Backends.word_lt_uint256_size -- private + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_add_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_sub_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_mul_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_div_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_mod_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_eq_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_iszero_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_lt_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_gt_native + -- Compiler.Proofs.YulGeneration.Backends.toNat_fromBool -- private + -- Compiler.Proofs.YulGeneration.Backends.uint256_lt_iff_nat_lt -- private + -- Compiler.Proofs.YulGeneration.Backends.slt_int256_eq_sltBool -- private + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_slt_native + -- Compiler.Proofs.YulGeneration.Backends.sgt_int256_eq_sgtBool -- private + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_sgt_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_sdiv_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_smod_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_sar_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_signextend_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_and_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_or_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_xor_native + -- Compiler.Proofs.YulGeneration.Backends.xor_all_ones_uint256_word -- private + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_not_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_shl_native + Compiler.Proofs.YulGeneration.Backends.evalPureBuiltinViaEvmYulLean_shr_native -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean -- Compiler.Proofs.YulGeneration.Backends.backends_agree_add -- private @@ -3743,146 +5309,47 @@ end Verity.AxiomAudit -- Compiler.Proofs.YulGeneration.Backends.backends_agree_calldatasize -- private -- Compiler.Proofs.YulGeneration.Backends.backends_agree_sload -- private -- Compiler.Proofs.YulGeneration.Backends.backends_agree_mappingSlot -- private - Compiler.Proofs.YulGeneration.Backends.backends_agree_on_bridged_builtins + -- Compiler.Proofs.YulGeneration.Backends.backends_agree_on_bridged_builtins -- private -- Compiler.Proofs.YulGeneration.Backends.backends_agree_on_keccak256 -- private - -- Compiler.Proofs.YulGeneration.Backends.evalYulExprWithBackend_verity_eq -- private - -- Compiler.Proofs.YulGeneration.Backends.evalYulExprsWithBackend_verity_eq -- private - Compiler.Proofs.YulGeneration.Backends.evalYulExprWithBackend_eq_on_bridged + -- Compiler.Proofs.YulGeneration.Backends.evalYulExprWithBackend_evmYulLean_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.evalYulExprsWithBackend_evmYulLean_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.evalYulExprWithBackend_eq_on_bridged -- private -- Compiler.Proofs.YulGeneration.Backends.evalYulExprsWithBackend_eq_on_bridged -- private - Compiler.Proofs.YulGeneration.Backends.evalYulExpr_evmYulLean_eq_on_bridged - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_verity_eq - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_let_eq_on_bridged - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_assign_eq_on_bridged - Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_nil - Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_cons - Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_append - Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_singleton - Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_snoc - Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_map_mstore - Compiler.Proofs.YulGeneration.Backends.BridgedStraightStmts_map_tstore + -- Compiler.Proofs.YulGeneration.Backends.evalYulExpr_evmYulLean_eq_on_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_evmYulLean_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_let_eq_on_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_assign_eq_on_bridged -- private -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_eq_on_bridged_straight_stmt -- private - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_eq_on_bridged_straight_stmts - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_block_eq_on_bridged_straight_stmts - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_if_eq_on_bridged_body - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_switch_eq_on_bridged_cases - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_for_eq_on_bridged_parts - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_nil - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_append - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_snoc + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_eq_on_bridged_straight_stmts -- private + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_block_eq_on_bridged_straight_stmts -- private + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_if_eq_on_bridged_body -- private + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_switch_eq_on_bridged_cases -- private + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_for_eq_on_bridged_parts -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_callvalue -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_calldatasize -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_selector -- private - Compiler.Proofs.YulGeneration.Backends.bridgedExpr_selectorExpr - Compiler.Proofs.YulGeneration.Backends.evalYulExprWithBackend_evmYulLean_selectorExpr_semantics + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_selectorExpr -- private + -- Compiler.Proofs.YulGeneration.Backends.evalYulExpr_selectorExpr_semantics -- private + -- Compiler.Proofs.YulGeneration.Backends.evalYulExprWithBackend_evmYulLean_selectorExpr_semantics -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_calldatasize_lt -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_has_selector -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_empty_calldata -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_iszero_ident -- private - Compiler.Proofs.YulGeneration.Backends.bridgedExpr_keccak256 - Compiler.Proofs.YulGeneration.Backends.bridgedExpr_mload - Compiler.Proofs.YulGeneration.Backends.bridgedExpr_tload - Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_let_mload - Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_let_tload - Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_let_keccak256 - Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_assign_mload - Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_assign_tload - Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_assign_keccak256 - Compiler.Proofs.YulGeneration.Backends.bridgedStraightStmt_log_of_bridged_args - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_of_bridgedStraightStmt - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_log_of_bridged_args - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_let_mload - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_let_tload - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_let_keccak256 - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_assign_mload - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_assign_tload - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_assign_keccak256 - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_mstore_of_bridged_args - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_tstore_of_bridged_args - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_sstore_mapping_of_bridged_args - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_sstore_lit_of_bridged_val - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_sstore_ident_of_bridged_val - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_sstore_add_of_bridged_args - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_stop - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_return_of_bridged_args - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_revert - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_leave - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_let_of_bridged_val - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_letMany - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_assign_of_bridged_val - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_comment - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_funcDef - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_of_BridgedStraightStmts - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_straight - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_straight - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_append_straight - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_map_mstore - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_block_of_bridgedStmts - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_block - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_block - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_if_of_bridgedStmts - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_if - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_if - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_for_of_bridgedStmts - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_for - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_for - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_switch_of_bridgedStmts - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_switch - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_switch - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_block_of_bridgedStraightStmts - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_if_of_bridgedStraightStmts - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_for_of_bridgedStraightStmts - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_map_tstore - Compiler.Proofs.YulGeneration.Backends.bridgedStmt_revert_zero - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_revert_zero - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_comment - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_comment - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_let - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_let - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_assign - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_assign - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_letMany - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_letMany - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_stop - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_stop - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_leave - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_leave - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_return - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_return - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_revert - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_revert - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_mstore - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_mstore - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_tstore - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_tstore - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_sstore_lit - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_sstore_lit - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_sstore_ident - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_sstore_ident - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_sstore_mapping - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_sstore_mapping - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_log - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_log - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_singleton_funcDef - Compiler.Proofs.YulGeneration.Backends.BridgedStmts_cons_funcDef - Compiler.Proofs.YulGeneration.Backends.callvalueGuard_bridged - Compiler.Proofs.YulGeneration.Backends.calldatasizeGuard_bridged + -- Compiler.Proofs.YulGeneration.Backends.callvalueGuard_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.calldatasizeGuard_bridged -- private Compiler.Proofs.YulGeneration.Backends.dispatchBody_bridged Compiler.Proofs.YulGeneration.Backends.defaultDispatchCase_bridged - -- Compiler.Proofs.YulGeneration.Backends.switchCases_bridged -- private + Compiler.Proofs.YulGeneration.Backends.switchCases_bridged Compiler.Proofs.YulGeneration.Backends.buildSwitch_bridged Compiler.Proofs.YulGeneration.Backends.mappingSlotFuncAt_bridged Compiler.Proofs.YulGeneration.Backends.runtimeCode_bridged Compiler.Proofs.YulGeneration.Backends.emitYul_runtimeCode_bridged - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_eq_on_bridged_target - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_eq_on_bridged_stmt - Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_eq_on_bridged_stmts - Compiler.Proofs.YulGeneration.Backends.emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies - Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend_eq_fuel - Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend_verity_eq - Compiler.Proofs.YulGeneration.Backends.interpretYulFromIR_evmYulLean_eq_on_bridged_bodies - Compiler.Proofs.YulGeneration.Backends.yulCodegen_preserves_semantics_evmYulLean + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_eq_on_bridged_target -- private + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_eq_on_bridged_stmt -- private + -- Compiler.Proofs.YulGeneration.Backends.execYulFuelWithBackend_eq_on_bridged_stmts -- private + -- Compiler.Proofs.YulGeneration.Backends.emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies -- private + -- Compiler.Proofs.YulGeneration.Backends.interpretYulRuntimeWithBackend_evmYulLean_eq -- private + -- Compiler.Proofs.YulGeneration.Backends.interpretYulFromIR_evmYulLean_eq_on_bridged_bodies -- private -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSignedArithSpec.lean Compiler.Proofs.YulGeneration.Backends.SignedArithSpec.specSignBit_lt_specModulus @@ -3903,16 +5370,48 @@ end Verity.AxiomAudit -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean Compiler.Proofs.YulGeneration.Backends.compileExpr_bridgedSource_leaf + Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_of_exprCompileCore + Compiler.Proofs.YulGeneration.Backends.bridgedSourceExpr_keccak256_of_exprCompileCore -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_binopBuiltin -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_unopBuiltin -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_nullaryBuiltin -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_yulBinOp -- private -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_yulNegatedBinOp -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_yulToBool -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_ceilDiv -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_mulDivDown -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_mulDivUp -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_wMulDown -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_wDivUp -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_min -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_max -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_ite -- private -- Compiler.Proofs.YulGeneration.Backends.compileExpr_yulBinOp_ok -- private -- Compiler.Proofs.YulGeneration.Backends.compileExpr_yulNegatedBinOp_ok -- private + -- Compiler.Proofs.YulGeneration.Backends.compileExpr_yulBoolBinOp_ok -- private + -- Compiler.Proofs.YulGeneration.Backends.compileExpr_unopBuiltin_ok -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_sload_lit -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_sload -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_mappingSlot -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_sload_mappingSlot_lit -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_sload_mappingSlot_lit_add -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_sload_mappingSlot2_lit -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_sload_mappingSlot2_lit_add -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_foldl_mappingSlot -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_sload_mappingSlotChain_lit -- private + -- Compiler.Proofs.YulGeneration.Backends.compileMappingSlotRead_bridged -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_adtTagRead_lit -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_adtFieldRead_lit -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_packed_sload_lit -- private + -- Compiler.Proofs.YulGeneration.Backends.bridgedExpr_packed_read -- private + -- Compiler.Proofs.YulGeneration.Backends.compileExpr_binaryShape_ok -- private + -- Compiler.Proofs.YulGeneration.Backends.compileExpr_ternaryShape_ok -- private Compiler.Proofs.YulGeneration.Backends.compileExpr_bridgedSource + Compiler.Proofs.YulGeneration.Backends.compileExpr_keccak256_bridgedSource_of_exprCompileCore -- Compiler.Proofs.YulGeneration.Backends.compileRequireFailCond_default_bridgedSource -- private Compiler.Proofs.YulGeneration.Backends.compileRequireFailCond_bridgedSource Compiler.Proofs.YulGeneration.Backends.compileExprList_bridgedSource + Compiler.Proofs.YulGeneration.Backends.compileExpr_mappingChain_bridgedSource -- Compiler/Proofs/YulGeneration/Backends/EvmYulLeanStateBridge.lean Batteries.RBNode.All.setBlack' @@ -3934,18 +5433,14 @@ end Verity.AxiomAudit -- Compiler.Proofs.YulGeneration.Backends.StateBridge.byteArray_get?_append_left -- private -- Compiler.Proofs.YulGeneration.Backends.StateBridge.byteArray_get?_append_right -- private -- Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_fold_get?_left -- private + -- Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_fold_get?_word -- private Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_size Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_selectorByte0 Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_selectorByte1 Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_selectorByte2 Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_selectorByte3 Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_arg0Byte - Compiler.Proofs.YulGeneration.Backends.StateBridge.callvalue_bridge - Compiler.Proofs.YulGeneration.Backends.StateBridge.timestamp_bridge - Compiler.Proofs.YulGeneration.Backends.StateBridge.number_bridge - Compiler.Proofs.YulGeneration.Backends.StateBridge.calldatasize_bridge - Compiler.Proofs.YulGeneration.Backends.StateBridge.caller_bridge - Compiler.Proofs.YulGeneration.Backends.StateBridge.address_bridge + Compiler.Proofs.YulGeneration.Backends.StateBridge.calldataToByteArray_argByte_of_drop_eq_cons -- Compiler.Proofs.YulGeneration.Backends.StateBridge.ordering_then_eq -- private -- Compiler.Proofs.YulGeneration.Backends.StateBridge.UInt256_compare_eq_fin -- private Compiler.Proofs.YulGeneration.Backends.StateBridge.UInt256_eq_of_compare_eq @@ -3961,43 +5456,46 @@ end Verity.AxiomAudit Compiler.Proofs.YulGeneration.Backends.StateBridge.uint256_roundtrip -- Compiler/Proofs/YulGeneration/Equivalence.lean - Compiler.Proofs.YulGeneration.resultsMatch_of_execResultsAligned - Compiler.Proofs.YulGeneration.statesAligned_refl - Compiler.Proofs.YulGeneration.execYulStmtsFuel_nil - Compiler.Proofs.YulGeneration.execYulStmtsFuel_cons - Compiler.Proofs.YulGeneration.execYulStmtFuel_for + -- Compiler.Proofs.YulGeneration.resultsMatch_of_execResultsAligned -- private + -- Compiler.Proofs.YulGeneration.statesAligned_refl -- private + -- Compiler.Proofs.YulGeneration.execYulStmtsFuel_nil -- private + -- Compiler.Proofs.YulGeneration.execYulStmtsFuel_cons -- private + -- Compiler.Proofs.YulGeneration.execYulStmtFuel_for -- private -- Compiler.Proofs.YulGeneration.stmt_align_contra -- private + -- Compiler.Proofs.YulGeneration.execIRStmtsFuel_equiv_execYulStmtsFuel_of_stmt_equiv -- private + -- Compiler.Proofs.YulGeneration.execIRStmtsFuel_equiv_execYulStmts_of_stmt_equiv -- private + -- Compiler.Proofs.YulGeneration.execIRFunctionFuel_equiv_interpretYulBodyFromState_of_stmt_equiv -- private + -- Compiler.Proofs.YulGeneration.ir_yul_function_equiv_fuel_goal_of_stmt_equiv -- private + -- Compiler.Proofs.YulGeneration.ir_yul_function_equiv_from_state_of_fuel_goal -- private + -- Compiler.Proofs.YulGeneration.ir_yul_function_equiv_from_state_of_fuel_goal_and_adequacy -- private + -- Compiler.Proofs.YulGeneration.ir_yul_function_equiv_from_state_of_stmt_equiv_and_adequacy -- private + -- Compiler.Proofs.YulGeneration.ir_yul_function_equiv_from_state_of_stmt_equiv -- private + + -- Compiler/Proofs/YulGeneration/IRFuel.lean Compiler.Proofs.YulGeneration.execIRStmtsFuel_nil Compiler.Proofs.YulGeneration.execIRStmtsFuel_cons - Compiler.Proofs.YulGeneration.execIRStmtsFuel_equiv_execYulStmtsFuel_of_stmt_equiv - Compiler.Proofs.YulGeneration.execIRStmtsFuel_equiv_execYulStmts_of_stmt_equiv - Compiler.Proofs.YulGeneration.execIRFunctionFuel_equiv_interpretYulBodyFromState_of_stmt_equiv - Compiler.Proofs.YulGeneration.ir_yul_function_equiv_fuel_goal_of_stmt_equiv Compiler.Proofs.YulGeneration.execIRFunctionFuel_adequate - Compiler.Proofs.YulGeneration.ir_yul_function_equiv_from_state_of_fuel_goal - Compiler.Proofs.YulGeneration.ir_yul_function_equiv_from_state_of_fuel_goal_and_adequacy - Compiler.Proofs.YulGeneration.ir_yul_function_equiv_from_state_of_stmt_equiv_and_adequacy - Compiler.Proofs.YulGeneration.ir_yul_function_equiv_from_state_of_stmt_equiv -- Compiler/Proofs/YulGeneration/ReferenceOracle/Builtins.lean - Compiler.Proofs.YulGeneration.evalBuiltinCall_callvalue_nil - Compiler.Proofs.YulGeneration.evalBuiltinCall_callvalue_context - Compiler.Proofs.YulGeneration.evalBuiltinCall_calldatasize_nil - Compiler.Proofs.YulGeneration.evalBuiltinCall_caller_nil - Compiler.Proofs.YulGeneration.evalBuiltinCall_address_nil - Compiler.Proofs.YulGeneration.evalBuiltinCall_timestamp_nil - Compiler.Proofs.YulGeneration.evalBuiltinCall_number_nil - Compiler.Proofs.YulGeneration.evalBuiltinCall_chainid_nil - Compiler.Proofs.YulGeneration.evalBuiltinCall_blobbasefee_nil - Compiler.Proofs.YulGeneration.calldataloadWord_offset4 - Compiler.Proofs.YulGeneration.evalBuiltinCall_calldataload_offset4_single - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackend_calldataload_offset4_single - Compiler.Proofs.YulGeneration.evalBuiltinCall_sload_single - Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackend_sload_single - - -- Compiler/Proofs/YulGeneration/ReferenceOracle/Semantics.lean + -- Compiler.Proofs.YulGeneration.defaultBuiltinBackend_eq_evmYulLean -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_callvalue_nil -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_callvalue_context -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_calldatasize_nil -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_caller_nil -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_address_nil -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_timestamp_nil -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_number_nil -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_chainid_nil -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_blobbasefee_nil -- private + -- Compiler.Proofs.YulGeneration.calldataloadWord_offset4 -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_calldataload_offset4_single -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackend_calldataload_offset4_single -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCall_sload_single -- private + -- Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackend_sload_single -- private + + -- Compiler/Proofs/YulGeneration/RuntimeTypes.lean Compiler.Proofs.YulGeneration.YulTransaction.ofIR_sender Compiler.Proofs.YulGeneration.YulTransaction.ofIR_args ] --- Total: 3732 theorems/lemmas (2782 public, 950 private, 0 sorry'd) +-- Total: 5212 theorems/lemmas (3508 public, 1704 private, 0 sorry'd) diff --git a/TRUST_ASSUMPTIONS.md b/TRUST_ASSUMPTIONS.md index 220639441..407bd97ab 100644 --- a/TRUST_ASSUMPTIONS.md +++ b/TRUST_ASSUMPTIONS.md @@ -58,10 +58,10 @@ Current theorem totals, property-test coverage, and proof status live in [docs/V ### 6. EVM/Yul Semantics and Gas - **Role**: Runtime execution model. -- **Status (Phase 4: full semantic integration for safe compiler-produced bodies)**: 25 universal pure bridge theorems (all fully proven) in `Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean`. All pure bridge cases are now covered by universal symbolic lemmas. Additionally, 11 context/env/storage/helper builtin bridge theorems bring the total to 36 of 36 builtins bridged, and `smod`/`sar` no longer depend on admitted bridge lemmas. The retargeting module `EvmYulLeanRetarget.lean` proves the pointwise theorem `backends_agree_on_bridged_builtins`, the expression-level theorem `evalYulExpr_evmYulLean_eq_on_bridged`, statement-fragment helpers for straight-line, block, if, switch, and for cases, the recursive target theorem `execYulFuelWithBackend_eq_on_bridged_target`, emitted-runtime closure/equality theorems, and `yulCodegen_preserves_semantics_evmYulLean`, which retargets the existing Layer-3 IR→Yul preservation theorem to `interpretYulRuntimeWithBackend .evmYulLean` under bridged-body hypotheses. `EvmYulLeanBodyClosure.lean` proves `compileStmtList_always_bridged`, a universal aggregation theorem for `BridgedSafeStmts`; the external-call family (`internalCall`, `internalCallAssign`, `externalCallBind`, and `ecm`) remains carved out behind explicit function-table hypotheses. `EndToEnd.lean` now exposes `layers2_3_ir_matches_yul_evmYulLean` without raw `BridgedStmts` body hypotheses by deriving them from `SupportedSpec`, static-parameter witnesses, and `BridgedSafeStmts` source-body witnesses. Gas is not modeled. -- **Trust boundary (EVMYulLean EndToEnd target)**: For `BridgedExpr` expressions, `BridgedStraightStmts` statement lists (including mapping-slot, literal-slot, and identifier-slot `sstore`), recursive `BridgedTarget` executions, source statement lists admitted by `BridgedSafeStmts`, emitted runtime wrappers whose embedded bodies satisfy `BridgedStmt`, Layer-3 contract executions whose body hypotheses are discharged, and the public EndToEnd wrapper that derives raw body bridges from source-level safe-body/static-param witnesses, the trust assumption moves from "Verity's custom builtin implementations are correct" to "EVMYulLean's execution model matches the EVM" (backed by upstream Ethereum conformance tests) with fully proven builtin bridge dependencies. +- **Status (native transition in progress)**: 25 universal pure bridge theorems (all fully proven) in `Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean`, plus 11 context/env/storage/helper builtin bridge theorems, cover the 36 builtin bridge cases used by the transition regressions. All pure bridge cases are now covered by universal symbolic lemmas. `EvmYulLeanRetarget.lean` now remains transition/regression evidence rather than public compiler-correctness authority. The public EndToEnd composition surface in `Compiler/Proofs/EndToEnd.lean` targets native `EvmYul.Yul.callDispatcher` execution through `Compiler.Proofs.YulGeneration.Backends.EvmYulLeanNativeHarness`: the public surface is `nativeResultsMatchOn`, `sourceResultMatchesNativeOn`, the source/native result-composition theorem over that native result surface, and the concrete SimpleStorage native theorem. The fuel-indexed `nativeIRRuntimeMatchesIR` seams are file-local. The legacy `YulGeneration.Preservation` contract preservation theorem and the higher-level function equivalence ladder in `YulGeneration.Equivalence` are file-local reference-oracle transition code, and root `Compiler.lean` no longer re-exports the legacy Yul proof stack. Deeper generated/supported-Yul preservation is not yet fully retargeted to native EVMYulLean; `ReferenceOracle.Semantics`, `legacyExecYulFuel`, and related fuel-based helpers remain inside the isolated legacy stack. Gas is not modeled. +- **Trust boundary (EVMYulLean EndToEnd target)**: For the native EndToEnd path, the runtime authority is EVMYulLean dispatcher execution after Verity Yul is lowered by the native harness and projected onto the observable result surface. The remaining legacy preservation/equivalence stack is transition evidence only until its generated/supported-Yul proofs are rebuilt directly against native EVMYulLean execution. - **Fork dependency**: Verity pins [`lfglabs-dev/EVMYulLean`](https://github.com/lfglabs-dev/EVMYulLean), a fork of [`NethermindEth/EVMYulLean`](https://github.com/NethermindEth/EVMYulLean). The pinned commit is recorded in `lake-manifest.json` under the `evmyul` package. The exact divergence from upstream is enumerated in [`artifacts/evmyullean_fork_audit.json`](artifacts/evmyullean_fork_audit.json), regenerated by `scripts/generate_evmyullean_fork_audit.py` and validated by `make check`. As of the current pin, the fork is 2 commits ahead of `upstream/main` and 0 behind; both commits are non-semantic (one visibility change on an exponentiation accumulator, one Lean 4.22.0 deprecation fix), so upstream Ethereum conformance test coverage applies transitively. In addition to the `make check` validation, a weekly scheduled GitHub Actions workflow ([`.github/workflows/evmyullean-fork-conformance.yml`](.github/workflows/evmyullean-fork-conformance.yml)) runs `make test-evmyullean-fork`, which re-verifies the fork audit artifact against `lake-manifest.json`, checks the EVMYulLean adapter report, rebuilds adapter correctness, rebuilds the native transition harness and smoke tests, rebuilds the public EndToEnd EVMYulLean target, and rebuilds the universal bridge lemmas (25 proven) together with the 123 concrete `native_decide` bridge-equivalence tests (`EvmYulLeanBridgeTest`), surfacing any upstream drift as a run annotation during the two-week `continue-on-error` burn-in ending 2026-05-04 and then as a red workflow plus an automatically opened or updated GitHub issue for scheduled/manual failures. -- **Remaining gap for whole-program retargeting**: The report generator now records status `full_semantic_integration`: `compileStmtList_always_bridged` is proven for the safe source-body whitelist, and `EndToEnd.lean` discharges the public theorem's raw external-function `BridgedStmts` body hypotheses for supported compiler-produced contracts. The remaining scope limit is the external-call/function-table family, which stays carved out of `BridgedSafeStmts`. +- **Remaining gap for whole-program retargeting**: The public EndToEnd native surface is in place, but whole-program generated/supported-Yul preservation still needs to be rebuilt directly over native EVMYulLean execution. The legacy reference-oracle preservation/equivalence modules remain importable as isolated transition code, and the external-call/function-table family stays carved out of `BridgedSafeStmts`. - **Implication**: Semantic correctness does not imply gas-safety. - **Proxy note**: `delegatecall`-based proxy / upgradeability flows still sit outside the current proof-interpreter model. Archive `--trust-report` and use `--deny-proxy-upgradeability` when proxy semantics must remain outside the selected verified subset (issue `#1420`). diff --git a/artifacts/evmyullean_adapter_report.json b/artifacts/evmyullean_adapter_report.json index 1e0cde9cb..9ad4feff4 100644 --- a/artifacts/evmyullean_adapter_report.json +++ b/artifacts/evmyullean_adapter_report.json @@ -219,8 +219,9 @@ "phase4_retarget": { "admitted_bridge_dependencies": [], "backends_agree_on_bridged_builtins": "proven", - "compileExpr_bridgedSource": "proven (pure source-expression fragment)", + "compileExpr_bridgedSource": "proven (source-expression fragment with parameter length, storage, and storage-array length reads, ADT tag/field reads, singleton and nested mapping reads through the abstract mappingSlot bridge, mapping struct-member reads, reserved exponentiation, boolean normalization, branchless helpers, bridged environment reads, and unary calldata/memory/transient reads)", "compileExpr_bridgedSource_leaf": "proven (scalar source-expression leaves)", + "compileExpr_mappingChain_bridgedSource": "proven (mappingChain source-expression wrapper through the abstract mappingSlot bridge)", "compileStmtList_always_bridged": "proven (universal compileStmtList body closure for BridgedSafeStmts; external-call family carved out)", "compileStmtList_binding_leaf_bridged": "proven (scalar let/assign statement lists)", "compileStmtList_external_body_fragment_bridged": "proven (mixed external body fragment)", @@ -248,12 +249,14 @@ "genParamLoads_scalar_bridged": "proven (scalar calldata parameters)", "genParamLoads_static_scalar_bridged": "proven (static scalar calldata parameters)", "genStaticTypeLoads_calldataload_bridged": "proven (static scalar calldata leaves)", - "layers2_3_ir_matches_yul_evmYulLean": "proven (body hypotheses discharged)", - "remaining_for_whole_program_retargeting": [], + "layers2_3_ir_matches_yul_evmYulLeanBackend": "removed from EndToEnd surface (retarget evidence isolated in EvmYulLeanRetarget.lean)", + "remaining_for_whole_program_retargeting": [ + "discharge the conditional EndToEnd theorem's bridged-body hypotheses for full compiler-produced contracts" + ], "retarget_file": "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean", - "status": "full_semantic_integration", - "trust_boundary": "recursive BridgedTarget statement fragment: EVMYulLean execution model matches EVM (upstream conformance tests) for BridgedExpr expressions, BridgedStraightStmts (including mapping-slot, literal-slot, and identifier-slot sstore), and recursively nested BridgedStmt targets; generated runtime-code closure, emitted-runtime backend equality, and the lower-level Layer-3 EVMYulLean retarget theorem are proven under bridged IR-body witnesses; the public EndToEnd safe-body wrapper discharges raw BridgedStmts body hypotheses from SupportedSpec, static-parameter, and BridgedSafeStmts source witnesses; compileStmtList_always_bridged proves a universal BridgedSafeStmts aggregation theorem with the external-call family carved out behind explicit function-table hypotheses", - "yulCodegen_preserves_semantics_evmYulLean": "proven (conditional on bridged IR bodies)" + "status": "universal-safe-body-closure", + "trust_boundary": "recursive BridgedTarget statement fragment: EVMYulLean execution model matches EVM (upstream conformance tests) for BridgedExpr expressions, BridgedStraightStmts (including mapping-slot, literal-slot, and identifier-slot sstore), and recursively nested BridgedStmt targets; generated runtime-code closure, emitted-runtime backend equality, and the lower-level Layer-3 EVMYulLean retarget theorem are proven under bridged IR-body witnesses; the EndToEnd safe-body backend-wrapper lemma is private transition plumbing, while public EndToEnd targets use native dispatcher execution through interpretIRRuntimeNative; compileStmtList_always_bridged proves a universal BridgedSafeStmts aggregation theorem with the external-call family carved out behind explicit function-table hypotheses", + "yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle": "missing" }, "schema_version": 7, "status": "ok", diff --git a/docs/ARITHMETIC_PROFILE.md b/docs/ARITHMETIC_PROFILE.md index 0347f48c3..ccf0b2bd6 100644 --- a/docs/ARITHMETIC_PROFILE.md +++ b/docs/ARITHMETIC_PROFILE.md @@ -34,7 +34,7 @@ Wrapping semantics are **proven** (not assumed) across all three verification la |-------|---------------|----------------| | Layer 1 (EDSL) | `Verity/Core/Uint256.lean` | `Uint256.add`, `sub`, `mul`, `pow`, `div`, `mod` are wrapping modular | | Layer 1 (EDSL) | `Verity/Proofs/Stdlib/Math.lean` | `safeAdd`, `safeSub`, `safeMul` correctness | -| Compiler reference oracle | `Compiler/Proofs/YulGeneration/ReferenceOracle/Builtins.lean` | `evalBuiltinCall` implements wrapping for all 15 pure builtins | +| Compiler reference oracle | `Compiler/Proofs/YulGeneration/ReferenceOracle/Builtins.lean` | `legacyEvalBuiltinCall` implements wrapping for all 15 pure builtins | | Compiler | `Compiler/Proofs/ArithmeticProfile.lean` | `add_wraps`, `sub_wraps`, `mul_wraps`, `div_by_zero`, `mod_by_zero` | | EVMYulLean bridge | `Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean` | Universal bridge lemmas for all 25 pure builtins (see list below) | | EVMYulLean bridge tests | `Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeTest.lean` | Regression vectors for the universal pure-builtin bridge lemmas | diff --git a/docs/DGX_SPARK_BOTTLENECK_REPORT.md b/docs/DGX_SPARK_BOTTLENECK_REPORT.md new file mode 100644 index 000000000..13fbfc9bb --- /dev/null +++ b/docs/DGX_SPARK_BOTTLENECK_REPORT.md @@ -0,0 +1,68 @@ +# DGX Spark CI Bottleneck Report + +Date: 2026-05-06 +Host: `spark-de79` / `dgx-spark-gpu-1` +Repo revision measured: `3157166c` (`main`) +Tooling: Lean 4.22.0, Lake 5.0.0, `LEAN_NUM_THREADS=4` except thread-scaling tests + +## Method + +I ran Verity CI-sized tasks directly on the DGX in an isolated checkout at `/tmp/verity-dgx-profile`, using the existing runner Lean package cache and a fresh `.lake/build` when measuring cold-ish build work. Each command was wrapped by `scripts/profile_ci_resources.py`, which records wall time, GNU `time -v`, `/proc/stat` CPU/iowait samples, `/proc/meminfo`, `/proc/diskstats`, and `nvidia-smi`. + +Raw result JSON and logs were left on the DGX under `/tmp/verity-dgx-results` and copied locally to `/tmp/verity-dgx-results` during analysis. + +## Stage Timings + +| Stage | Command | Wall | Effective CPU | Peak RSS | Disk writes | GPU util | +| --- | --- | ---: | ---: | ---: | ---: | ---: | +| Python/check gate | `make check` | 33.6s | 99% | 64 MiB | 7.8 MB | 0% | +| Root Lean build, cold-ish | `lake build` | 112.4s | 188% | 1.6 GiB | 232 MB | 0% | +| Root Lean build, warm | `lake build` | 0.5s | 90% | 526 MiB | 0 MB | 0% | +| Full proof/axiom target | `lake build PrintAxioms` | 238.5s | 399% | 3.0 GiB | 733 MB | 0% | +| Axiom report execution | `lake env lean PrintAxioms.lean` | 80.2s | 104% | 1.7 GiB | 5.8 MB | 0% | +| Compiler/interpreter exes | `lake build verity-compiler verity-compiler-patched difftest-interpreter gas-report` | 80.5s | 271% | 1.8 GiB | 1001 MB | 0% | + +## Thread Scaling + +| `LEAN_NUM_THREADS` | `lake build` wall | Effective CPU | Peak RSS | +| ---: | ---: | ---: | ---: | +| 1 | 161.3s | 127% | 1.6 GiB | +| 2 | 123.5s | 169% | 1.7 GiB | +| 4 | 112.4s | 188% | 1.6 GiB | +| 8 | 110.9s | 191% | 1.6 GiB | + +More cores help up to about 4 Lean threads, then flatten. The 20-core DGX is not close to saturated for the root build; average host CPU was about 10% of 20 cores, i.e. roughly two cores. This is dependency graph and single-module elaboration limited, not hardware core-count limited. + +## Module Hotspots + +Selected module `:olean` rebuild times after priming dependencies with `lake build PrintAxioms`: + +| Module | Rebuild time | +| --- | ---: | +| `PrintAxioms` | 81.0s | +| `Compiler.Proofs.IRGeneration.SourceSemantics` | 31.3s | +| `Compiler.Proofs.IRGeneration.FunctionBody` | 19.3s | +| `Compiler.MainTest` | 17.2s | +| `Compiler.Proofs.EndToEnd` | 13.1s | +| `Compiler.Proofs.IRGeneration.Function` | 8.4s | +| `Compiler.TypedIRCompilerCorrectness` | 8.1s | +| `Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeLemmas` | 7.5s | +| `Compiler.Proofs.YulGeneration.StatementEquivalence` | 4.8s | +| `Compiler.Proofs.YulGeneration.Preservation` | 4.0s | + +## Bottlenecks + +1. `lake build PrintAxioms` is the largest CI-sized stage measured at 238s. It uses about four effective cores and only 3 GiB RSS, so it is compute/elaboration bound, not RAM, disk, or GPU bound. +2. `lake env lean PrintAxioms.lean` costs another 80s and is effectively single-core. The biggest actionable single target is the generated `PrintAxioms` file/report path. +3. Root `lake build` has poor scaling beyond 2-4 Lean threads. Upgrading to more CPU cores will not materially improve it unless the Lean dependency graph or hotspot modules are split. +4. Compiler executable builds write about 1 GB and use ~2.7 effective cores, but iowait stayed near zero. Disk bandwidth is not the limiting factor on the DGX NVMe. +5. `make check` is single-core Python and already short. Optimizing it is lower leverage unless it starts growing. +6. GPU utilization was 0% for all Verity CI workloads tested. GPU upgrades will not speed up these Lean/Python/compiler tasks. + +## Recommendations + +1. Optimize `PrintAxioms` first: reduce generated theorem set size where possible, split the generated file by namespace/package, or cache/report only changed theorem groups. This is the biggest direct win. +2. Split large Lean hotspots, especially `IRGeneration.SourceSemantics`, `IRGeneration.FunctionBody`, `Compiler.MainTest`, and `EndToEnd`, so Lake has more independent ready work and less single-module elaboration. +3. Keep `LEAN_NUM_THREADS` around 4 for DGX Verity CI. Higher values add little for root builds and can increase contention for other DGX work. +4. Do not buy more RAM or faster storage for this workload. Peak observed memory was under 9 GiB host-used during these runs on a 119 GiB machine, and iowait was consistently near zero. +5. Keep the DGX useful as a fast ARM64 Lean lane, but treat it as CPU-bound Lean infrastructure, not GPU acceleration infrastructure. diff --git a/docs/INTERPRETER_FEATURE_MATRIX.md b/docs/INTERPRETER_FEATURE_MATRIX.md index 93c1efcdb..03dbf9d66 100644 --- a/docs/INTERPRETER_FEATURE_MATRIX.md +++ b/docs/INTERPRETER_FEATURE_MATRIX.md @@ -12,7 +12,7 @@ Machine-readable version: [`artifacts/interpreter_feature_matrix.json`](../artif | Interpreter | File | Entry Point | Purpose | |---|---|---|---| | **IRInterpreter** | `Compiler/Proofs/IRGeneration/IRInterpreter.lean` | `execIRStmts` | Layer-2 preservation proofs | -| **YulSemantics reference oracle** | `Compiler/Proofs/YulGeneration/ReferenceOracle/Semantics.lean` | `execYulFuel` | Historical Layer-3 Yul execution semantics retained for regression comparisons | +| **YulSemantics reference oracle** | `Compiler/Proofs/YulGeneration/ReferenceOracle/Semantics.lean` | `legacyExecYulFuel` | Historical Layer-3 Yul execution semantics retained for regression comparisons | | **EVMYulLean bridge** | `Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeTest.lean` | `evalBuiltinCallViaEvmYulLean` | Pure builtin evaluation via EVMYulLean UInt256 | The old `SpecInterpreter` module has been removed. Source semantics now live in diff --git a/docs/IR_STORAGE_PHASE1_PLAN.md b/docs/IR_STORAGE_PHASE1_PLAN.md index fec09d7be..329a4e123 100644 --- a/docs/IR_STORAGE_PHASE1_PLAN.md +++ b/docs/IR_STORAGE_PHASE1_PLAN.md @@ -16,9 +16,9 @@ flip lands in subsequent commits on this branch. and round-trip lemmas (PR #1753, Phase 0). - `IRState.storage : Nat → IRStorageWord` is rfl-identical to `Nat → Nat` under the abbrev, so the Phase 0 retype required no callsite changes. -- The public theorem `simpleStorage_endToEnd_native_evmYulLean` retains - `hRetrieveHit` and `hStoreHit` as explicit hypotheses (#1743 commit - `fe63b826`). +- The public theorem `simpleStorage_endToEnd_native_evmYulLean` originally + retained `hRetrieveHit` and `hStoreHit` as explicit hypotheses (#1743 commit + `fe63b826`); later native bridge work discharged those premises. ## Phase 1 deliverables @@ -45,7 +45,7 @@ flip lands in subsequent commits on this branch. | `IRStorageWord` carrier | `Compiler/Proofs/IRGeneration/IRStorageWord.lean` | migrate | Flipped from `abbrev := Nat` to `@[reducible] def := UInt256`. Added `OfNat`, `Inhabited` instances and reproved round-trip lemmas (`toNat_ofNat = n % UInt256.size`, `ofNat_toNat = w`, `toNat_lt_size`). | | `abstractStoreMappingEntry` | `Compiler/Proofs/MappingSlot.lean:83` | migrate | Wraps `value : Nat` via `IRStorageWord.ofNat` inside the helper; simp lemma `abstractStoreMappingEntry_eq` updated to match. | | `abstractStoreStorageOrMapping` | `Compiler/Proofs/MappingSlot.lean:95` | migrate | Wraps `value : Nat` via `IRStorageWord.ofNat`; simp lemma `abstractStoreStorageOrMapping_eq` updated. | -| `evalBuiltinCallWithContext` (sload) | `Compiler/Proofs/YulGeneration/ReferenceOracle/Builtins.lean:58` | migrate | Projects `abstractLoadStorageOrMapping storage slot : IRStorageWord` back to `Nat` via `.toNat` for the `Option Nat` return. | +| `legacyEvalBuiltinCallWithContext` (sload) | `Compiler/Proofs/YulGeneration/ReferenceOracle/Builtins.lean:58` | migrate | Projects `abstractLoadStorageOrMapping storage slot : IRStorageWord` back to `Nat` via `.toNat` for the `Option Nat` return. | | `evalBuiltinCallViaEvmYulLean` (sload) | `Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean:1064` | migrate | Same `.toNat` projection on the EVMYulLean adapter sload branch. | | `IRInterpreter.evalIRStatementWithBackend` | `Compiler/Proofs/IRGeneration/IRInterpreter.lean` | safe | All `state.storage` reads go through `abstractLoadStorageOrMapping`, all writes go through `abstractStoreStorageOrMapping` / `abstractStoreMappingEntry`, so the helper-internal wrapping covers every callsite without changes here. Initial-state literal `fun _ => 0` continues to elaborate via the `OfNat IRStorageWord 0` instance. | | `EvmYulLeanBridgeLemmas` | `Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean` | safe | Builtin-equivalence lemmas thread `storage : Nat → IRStorageWord` as a parameter but never inspect the value; survive carrier flip without edits. | @@ -66,9 +66,8 @@ flip lands in subsequent commits on this branch. - `lake build` clean. - `make check` clean. - Every `Contracts/*/Proofs/` spec theorem unchanged (no signature drift). -- Public theorem `simpleStorage_endToEnd_native_evmYulLean` still carries - `hRetrieveHit` and `hStoreHit` premises — Phase 1 does not yet discharge - them. That work is Phase 2 / Phase 3. +- Public theorem `simpleStorage_endToEnd_native_evmYulLean` keeps building; + the later Phase 2 / Phase 3 work discharges the retrieve/store hit premises. ## Status @@ -76,5 +75,6 @@ Carrier flip implemented. `IRStorageWord` is now `@[reducible] def := UInt256` with `OfNat` / `Inhabited` instances and the round-trip lemmas restated for the new carrier. Downstream callsites have been migrated (helpers wrap `Nat → IRStorageWord` internally; sload sites project via `.toNat`). `lake build` clean, `make check` -green (600 tests). `hRetrieveHit` / `hStoreHit` remain on -`simpleStorage_endToEnd_native_evmYulLean`; their discharge is Phase 2 / Phase 3. +green (600 tests). The later Phase 2 / Phase 3 bridge work discharges the +`hRetrieveHit` / `hStoreHit` premises from +`simpleStorage_endToEnd_native_evmYulLean`. diff --git a/docs/IR_STORAGE_PHASE2_PLAN.md b/docs/IR_STORAGE_PHASE2_PLAN.md index 015a60c3a..265e43aa8 100644 --- a/docs/IR_STORAGE_PHASE2_PLAN.md +++ b/docs/IR_STORAGE_PHASE2_PLAN.md @@ -1,9 +1,15 @@ # IR Storage Refactor — Phase 2 Plan -Phase 2 of [`IR_STORAGE_UINT256_REFACTOR.md`](IR_STORAGE_UINT256_REFACTOR.md): -discharge `simpleStorageNativeRetrieveHitBridge` once Phase 1 lands the -`UInt256`-bounded IR storage carrier, then drop the `hRetrieveHit` premise from -`simpleStorage_endToEnd_native_evmYulLean`. +Phase 2 of [`IR_STORAGE_UINT256_REFACTOR.md`](IR_STORAGE_UINT256_REFACTOR.md) +originally tracked discharging the retrieve-hit fuel-wrapper bridge after the +`UInt256`-bounded IR storage carrier landed. + +Status update: this plan has been superseded for the public native path. The +public `simpleStorage_endToEnd_native_evmYulLean` theorem now consumes the +direct native-vs-IR `simpleStorageNativeRetrieveHitMatchBridge_proved` proof +through `simpleStorageNativeCallDispatcherMatchBridge_of_per_case`. The older +retrieve-hit compatibility theorem has been +removed with the obsolete SimpleStorage fuel-wrapper bridge surface. This file is the working scaffold for the Phase 2 PR. It is plan-only so the PR opens against a green build. @@ -32,8 +38,8 @@ parent transition note: ## Phase 2 deliverables -1. Lemma `simpleStorageNativeRetrieveHitBridge_proved` — analogous to the - already-discharged `simpleStorageNativeSelectorMissBridge_proved`. +1. Lemma `simpleStorageNativeRetrieveHitMatchBridge_proved` — analogous to the + direct selector-miss native match proof. 2. Replace the explicit `hRetrieveHit` premise on `simpleStorage_endToEnd_native_evmYulLean` with the proved lemma. 3. `PrintAxioms` for the public theorem no longer lists the retrieve-hit @@ -65,7 +71,7 @@ the carrier flip, to: ## Exit criteria -- `simpleStorageNativeRetrieveHitBridge_proved` lands and is invoked at the +- `simpleStorageNativeRetrieveHitMatchBridge_proved` lands and is invoked at the call site of the former `hRetrieveHit` premise. - `simpleStorage_endToEnd_native_evmYulLean` no longer carries `hRetrieveHit`. - `PrintAxioms` reflects the drop. @@ -73,5 +79,7 @@ the carrier flip, to: ## Status -Plan-only. Implementation depends on Phase 1 (#1754) landing first. The -`hStoreHit` premise remains and is handled by Phase 3. +Superseded for the public native SimpleStorage theorem. The direct retrieve-hit +proof is `simpleStorageNativeRetrieveHitMatchBridge_proved`; the generic +compatibility cleanup remains tracked in +[`NATIVE_EVMYULLEAN_TRANSITION.md`](NATIVE_EVMYULLEAN_TRANSITION.md). diff --git a/docs/IR_STORAGE_PHASE3_PLAN.md b/docs/IR_STORAGE_PHASE3_PLAN.md index f9d849e9a..74b44ba5d 100644 --- a/docs/IR_STORAGE_PHASE3_PLAN.md +++ b/docs/IR_STORAGE_PHASE3_PLAN.md @@ -1,9 +1,15 @@ # IR Storage Refactor — Phase 3 Plan -Phase 3 of [`IR_STORAGE_UINT256_REFACTOR.md`](IR_STORAGE_UINT256_REFACTOR.md): -discharge `simpleStorageNativeStoreHitBridge` and drop the `hStoreHit` premise -from `simpleStorage_endToEnd_native_evmYulLean`. After Phase 3, the public -SimpleStorage native theorem has zero remaining bridge premises. +Phase 3 of [`IR_STORAGE_UINT256_REFACTOR.md`](IR_STORAGE_UINT256_REFACTOR.md) +originally tracked discharging the store-hit fuel-wrapper bridge and dropping the +`hStoreHit` premise from `simpleStorage_endToEnd_native_evmYulLean`. + +Status update: this plan has been superseded for the public native path. The +public `simpleStorage_endToEnd_native_evmYulLean` theorem now consumes the +direct native-vs-IR `simpleStorageNativeStoreHitMatchBridge_proved` proof +through `simpleStorageNativeCallDispatcherMatchBridge_of_per_case`. The older +store-hit compatibility theorem has been +removed with the obsolete SimpleStorage fuel-wrapper bridge surface. This file is the working scaffold for the Phase 3 PR. It is plan-only so the PR opens against a green build. @@ -30,14 +36,14 @@ The store-hit case has two distinct read paths and one write path: ## Phase 3 deliverables -1. Lemma `simpleStorageNativeStoreHitBridge_proved` — mirrors the Phase 2 +1. Lemma `simpleStorageNativeStoreHitMatchBridge_proved` — mirrors the Phase 2 retrieve-hit lemma, with the additional sstore mutation argument. 2. Replace the explicit `hStoreHit` premise on `simpleStorage_endToEnd_native_evmYulLean` with the proved lemma. 3. `PrintAxioms` for the public theorem reports no remaining bridge premises beyond the trusted EVMYulLean builtin axioms. -4. `simpleStorageNativeCallDispatcherBridge_of_per_case` is the only - surviving dispatcher surface and is fully closed. +4. `simpleStorageNativeCallDispatcherMatchBridge_of_per_case` is the surviving + dispatcher surface and is fully closed. 5. `Contracts/SimpleStorage/Proofs/` unchanged. ## Proof obligation outline @@ -64,7 +70,7 @@ After Phases 1 and 2, the store-hit bridge reduces to: ## Exit criteria -- `simpleStorageNativeStoreHitBridge_proved` lands and is invoked at the +- `simpleStorageNativeStoreHitMatchBridge_proved` lands and is invoked at the call site of the former `hStoreHit` premise. - `simpleStorage_endToEnd_native_evmYulLean` has zero remaining bridge premises. @@ -80,5 +86,7 @@ PR. ## Status -Plan-only. Implementation depends on Phases 1 (#1754) and 2 (#1755) landing -first. +Superseded for the public native SimpleStorage theorem. The direct store-hit +proof is `simpleStorageNativeStoreHitMatchBridge_proved`; the generic +compatibility cleanup remains tracked in +[`NATIVE_EVMYULLEAN_TRANSITION.md`](NATIVE_EVMYULLEAN_TRANSITION.md). diff --git a/docs/IR_STORAGE_UINT256_REFACTOR.md b/docs/IR_STORAGE_UINT256_REFACTOR.md index 1c4acb2bf..4747ae71c 100644 --- a/docs/IR_STORAGE_UINT256_REFACTOR.md +++ b/docs/IR_STORAGE_UINT256_REFACTOR.md @@ -1,17 +1,20 @@ # IR Storage Type Refactor: `Nat → Nat` ⇒ `Nat → UInt256` -Tracking the structural refactor that closes the retrieve-hit and store-hit -sub-bridges of `simpleStorageNativeCallDispatcherBridge` — and, more -generally, every per-case native dispatcher bridge that observes a value -read from storage. +Tracking the structural refactor that originally targeted the retrieve-hit and +store-hit compatibility sub-bridges of the SimpleStorage native dispatcher. +The public native SimpleStorage path has since moved to the direct native-vs-IR +`simpleStorageNativeCallDispatcherMatchBridge_of_per_case` splitter, with +`simpleStorageNativeRetrieveHitMatchBridge_proved` and +`simpleStorageNativeStoreHitMatchBridge_proved` discharging those cases. ## Why this exists -The first executable instantiation of the native dispatcher bridge -discharges `simpleStorageNativeSelectorMissBridge` but leaves -`simpleStorageNativeRetrieveHitBridge` and -`simpleStorageNativeStoreHitBridge` as explicit hypotheses on the public -theorem `simpleStorage_endToEnd_native_evmYulLean`. +The first executable instantiation of the native dispatcher bridge discharged +the selector-miss compatibility bridge but left retrieve-hit and store-hit +fuel-wrapper bridges as explicit hypotheses on the public theorem +`simpleStorage_endToEnd_native_evmYulLean`. That historical fuel-wrapper route +has been removed for SimpleStorage: the public native theorem consumes direct +match proofs for selector miss, retrieve hit, and store hit. Those two cases cannot be discharged inside the current public theorem signature because of a type-level mismatch: @@ -114,7 +117,7 @@ Deliverables: Exit criteria: `lake build` clean; every existing per-contract spec proof in `Contracts//Proofs/` still passes (no spec regressions). -### Phase 2 — discharge `simpleStorageNativeRetrieveHitBridge` +### Phase 2 — discharge retrieve hit With storage values bounded by construction on the IR side, the native projection's `% UInt256.size` truncation becomes the identity on the @@ -122,15 +125,17 @@ relevant slot. The retrieve-hit return-value chain reduces because the `mstore`'d native bytes and the IR-oracle return word agree. Deliverables: -- A proved `simpleStorageNativeRetrieveHitBridge_proved` lemma analogous - to `simpleStorageNativeSelectorMissBridge_proved`. -- Drop the `hRetrieveHit` premise from - `simpleStorage_endToEnd_native_evmYulLean`. +- Historical compatibility proof: + `simpleStorageNativeRetrieveHitMatchBridge_proved`. +- Public native direct proof: + `simpleStorageNativeRetrieveHitMatchBridge_proved`. +- `simpleStorage_endToEnd_native_evmYulLean` consumes the direct per-case + splitter without a retrieve-hit premise. -Exit criteria: `PrintAxioms` for the public theorem no longer lists the -retrieve-hit bridge; `lake build` clean; `make check` clean. +Status: complete for the public native theorem. The compatibility proof remains +only for the generic fuel-wrapper/reference-oracle cleanup. -### Phase 3 — discharge `simpleStorageNativeStoreHitBridge` +### Phase 3 — discharge store hit Same argument as Phase 2 for the store-hit case: the written value flows through bounded storage and the re-read of any other materialized @@ -138,20 +143,23 @@ observable slot agrees. The calldata round-trip was already 32-byte bounded, so the writeback case becomes mechanical. Deliverables: -- A proved `simpleStorageNativeStoreHitBridge_proved` lemma. -- Drop the `hStoreHit` premise from - `simpleStorage_endToEnd_native_evmYulLean`. +- Historical compatibility proof: + `simpleStorageNativeStoreHitMatchBridge_proved`. +- Public native direct proof: + `simpleStorageNativeStoreHitMatchBridge_proved`. +- `simpleStorage_endToEnd_native_evmYulLean` consumes the direct per-case + splitter without a store-hit premise. -Exit criteria: the public SimpleStorage native theorem has zero -remaining bridge premises beyond what the selector dispatcher already -discharges; `simpleStorageNativeCallDispatcherBridge_of_per_case` is -the only remaining surface and it is fully closed. +Status: complete for the public native theorem. The compatibility proof remains +only for the generic fuel-wrapper/reference-oracle cleanup. ### Phase 4 — generalize and retire the per-case bridge surface -Replace the per-contract `simpleStorageNative*Bridge` family with a -generic, dispatcher-shape-driven bridge so future contracts inherit -discharge automatically. +Replace the per-contract SimpleStorage direct-match family with a generic, +dispatcher-shape-driven bridge so future contracts inherit discharge +automatically. The older non-`Match` SimpleStorage bridge family is +compatibility-only and should disappear with the generic +fuel-wrapper/reference-oracle cleanup. Deliverables: - Generic `nativeCallDispatcherBridge_of_typed_storage` lemma over the @@ -163,10 +171,11 @@ Deliverables: ## Acceptance signals - `simpleStorage_endToEnd_native_evmYulLean` has no `hRetrieveHit` or - `hStoreHit` premise. -- `PrintAxioms` for the public theorem reports no bridge axioms beyond - the trusted `EvmYulLean` builtin axioms inherited from the existing - bridge-lemma set. + `hStoreHit` premise and consumes + `simpleStorageNativeCallDispatcherMatchBridge_of_per_case`. +- `PrintAxioms` includes the direct match proofs for the public native theorem; + compatibility bridge proofs may remain only while the generic + fuel-wrapper/reference-oracle family remains. - `Contracts/SimpleStorage/Proofs/` spec theorems are unchanged. - A second contract (e.g. Counter) lifts to the native theorem under the generic Phase-4 surface without contract-specific bridge code. diff --git a/docs/NATIVE_EVMYULLEAN_DONE_GRAPH.md b/docs/NATIVE_EVMYULLEAN_DONE_GRAPH.md index 0a35a7b87..402a28a9f 100644 --- a/docs/NATIVE_EVMYULLEAN_DONE_GRAPH.md +++ b/docs/NATIVE_EVMYULLEAN_DONE_GRAPH.md @@ -31,7 +31,7 @@ N0 generated-fragment contract -> N3 native dispatcher skeleton -> N4 body temp/write preservation -> N5 generated statement/expression native equivalence - -> N6 whole runtime native/interpreter agreement + -> N6 whole runtime native/EVMYulLean agreement -> N7 fuel adequacy / theorem-facing fuel story -> N8 public Layer 3 theorem flip -> N10 CI/docs enforcement @@ -58,7 +58,73 @@ N8 public Layer 3 theorem flip - **Urgency**: P0 - **Depends on**: none - **Blocks**: N1, N3, N4, N5, N6 -- **Status**: partially implicit in existing lowering/proof modules. +- **Status**: partially implicit in existing lowering/proof modules. Generated + dispatcher selector lookup now has native-lowering specializations + `lowerSwitchCasesNativeWithSwitchIds_find?_some_of_find_function` and + `lowerSwitchCasesNativeWithSwitchIds_find?_none_of_find_function`, bridging + `IRFunction` selector hits and misses to lowered native case lookup facts. + The actual `buildSwitch` source case list is named by + `buildSwitchSourceCases`, proved equal to `switchCases` by + `buildSwitchSourceCases_eq_switchCases`, and consumed directly by + `lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_some_of_find_function` + and `lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function`. + The singleton dispatcher-only runtime lowering boundary now lives in the + native harness as `lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative`. + Helper-free emitted runtime lowering is packaged by + `lowerRuntimeContractNative_emitYul_noMapping_noInternals_noFallback_noReceive`, + with the compiled supported no-mapping wrapper + `lowerRuntimeContractNative_of_compile_ok_supported_noMapping`. The generated + mapping-helper lowering is named by `nativeMappingSlotFunctionDefinition` and + `lowerFunctionDefinitionNativeWithReserved_mappingSlotFuncAt_zero`, pinning + the concrete native EVMYulLean function body for `mappingSlot` at scratch + base zero. Mapping-enabled emitted-runtime lowering is now packaged by + `lowerRuntimeContractNative_emitYul_mapping_noInternals_noFallback_noReceive_reserved` + and the compiled supported wrapper + `lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved`; the + dispatcher is lowered under the full emitted-runtime reserved-name context so + native switch temporary allocation remains faithful. Successful full native + lowering is now peeled back to its concrete dispatcher lowering by + `lowerRuntimeContractNative_emitYul_noMapping_ok_dispatcher`, + `lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher`, + `lowerRuntimeContractNative_emitYul_mapping_ok_dispatcher_reserved`, and + `lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved`. + EndToEnd also + names the positive/projected no-mapping dispatcher-statement wrappers + `nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping` + and + `nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping`, + plus their `_ofIR_environment` and `_ofIR_globalDefaults` variants and the + corresponding direct + `layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_*` + and `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_*` + wrappers. The same native dispatcher-statement surface now exists for + mapping-enabled generated runtimes under the `_mapping_reserved` names, + including `nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_*`, + `layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_*`, + and `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_*` + `_ofIR_environment` / `_ofIR_globalDefaults` variants. The + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_*` + wrappers compose successful full runtime lowering with the concrete + dispatcher-statement surfaces, keeping callers at the emitted-runtime + boundary while the exact dispatcher lowering is extracted internally. The + `layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_*` + wrappers lift that same full-runtime boundary to Layer 3, and + `layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_*` + lifts it to the Layers 2+3 composition. + Generic `.block` lowering shape also lives in the native harness via + `lowerStmtsNative_single_block_ok_singleton` and + `lowerStmtsNative_block_stmts_eq`; let/if/switch dispatcher statement peels + are named by `lowerStmtsNativeWithSwitchIds_let_head_eq`, + `lowerStmtsNativeWithSwitchIds_if_head_eq`, and + `lowerStmtsNativeWithSwitchIds_singleton_switch_eq`; default-revert switch + lowering is pinned by `lowerStmtsNativeWithSwitchIds_revert_zero_zero`, + `lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq`, and + `lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered`. + The combined no-fallback/no-receive generated dispatcher lowering shape is + exposed as `buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered`; + its selector hit/miss lookup companions are + `buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function` + and `buildSwitch_noFallback_noReceive_lowered_inner_find?_none_of_find_function`. - **Definition of done**: - The compiler-emitted runtime Yul fragment is explicitly characterized. - Allowed statements, expressions, builtins, helper functions, dispatcher @@ -80,6 +146,15 @@ N8 public Layer 3 theorem flip coverage. `chainid` and `blobbasefee` fail closed unless representable. Header-derived builtins without Verity transaction fields now also fail closed on selected native runtime paths. + `validateNativeRuntimeEnvironment_ofIR_representableEnvironment` and + `validateNativeRuntimeEnvironment_ofIR_globalDefaults` package the common + `YulTransaction.ofIR` validation cases once unsupported selected-path header + builtin use has been ruled out. EndToEnd mirrors the global-default case for + the compiled native positive and projected-result seams. + `generatedRuntimeNativeFragment_of_compile_ok_supported_safe` and + `validateGeneratedRuntimeNativeFragment_of_compile_ok_supported_safe` close + the executable generated-runtime fragment validator for supported compiled + contracts. - **Definition of done**: - Every environment field reachable from generated Yul is bridged, explicitly defaulted under a theorem invariant, or rejected fail-closed. @@ -97,7 +172,52 @@ N8 public Layer 3 theorem flip - **Depends on**: N1 - **Blocks**: N6, N8 - **Status**: projection coverage exists for success, stop, return, revert, - hard native errors, storage rollback, logs, and storage projection. + hard native errors, storage rollback, logs, and storage projection. The + generic + `exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq` + lemma packages generated selector-miss native `Revert` execution with the + exact projected rollback result for arbitrary one-word selector tags. The + generic + `exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq` lemma + packages selector-hit native halt/error execution with the selected body's + projected result at the full lowered-switch boundary; its store-parametric + companion + `exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq` + covers selector switches entered after earlier dispatcher-local bindings. + The selector-miss companion + `exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_projectResult_eq` + gives the same exact rollback package for store-parametric miss/default + paths. The block-level + `exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_projectResult_eq` + wrapper lifts that package through the generated dispatcher-local + `__has_selector` binding shape, while + `exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq` + packages selector-hit halt/error projection through the same block shape. + Selector-hit normal-success projection is now packaged by + `exec_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq`, + `exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq` + and its dispatcher-block companion + `exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq`. + The final direct dispatcher-match surface also has the endpoint-agnostic + `nativeDispatcherExecMatchesIRPositive_of_project_eq_match`, which lets a + generated runtime proof discharge the positive native-vs-IR target from one + projected native `YulResult` equality plus the observable IR match. The + corresponding runtime lifts are named by + `nativeIRRuntimeMatchesIR_of_lowered_dispatcherExec_project_eq_match` and + `nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_project_eq_match`. + EndToEnd now mirrors this as compiled-contract projected-result and + environment-closure seams: + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_eq_match`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_environment`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_globalDefaults`, + `layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_external_bodies_match`, + `layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_body_closure`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_external_bodies_match`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_match`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_environment`, + and `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_globalDefaults`. - **Definition of done**: - Projection lemmas cover every native halt/error/result used by generated runtime execution. @@ -118,7 +238,7 @@ N8 public Layer 3 theorem flip hit/miss lemmas, and raw lowered switch block bridge lemmas are in progress. - **Definition of done**: - The lowered dispatcher switch executes the same selected/default branch as - the interpreter oracle for every generated dispatcher shape. + the EVMYulLean fuel wrapper for every generated dispatcher shape. - The result is stated at the raw `lowerNativeSwitchBlock` boundary and at the higher generated dispatcher boundary. - **Verification**: @@ -187,7 +307,7 @@ N8 public Layer 3 theorem flip complete. - **Definition of done**: - For compiler-generated runtime Yul, native `callDispatcher` execution - agrees with the current interpreter-backed public semantic path on the + agrees with the current EVMYulLean-backed public semantic path on the observable result. - The theorem covers selected public function dispatch, default dispatch, storage, logs, return/revert/error behavior, and generated helper calls. diff --git a/docs/NATIVE_EVMYULLEAN_FULL_TRANSITION_DONE.md b/docs/NATIVE_EVMYULLEAN_FULL_TRANSITION_DONE.md index 15d976def..a24367fb4 100644 --- a/docs/NATIVE_EVMYULLEAN_FULL_TRANSITION_DONE.md +++ b/docs/NATIVE_EVMYULLEAN_FULL_TRANSITION_DONE.md @@ -4,19 +4,22 @@ This document defines what it means to finish the transition from Verity's custom Yul interpreter to native EVMYulLean execution as the authoritative compiler-verification target. -It is stricter than the current storage-semantics milestone. The SimpleStorage +It is stricter than the current native EndToEnd surface. The SimpleStorage native theorem now discharges its retrieve, store, and selector bridge cases, -but the generic compiler theorem stack still uses Verity's custom fuel-based -Yul interpreter through: +and the public generated-dispatcher theorem family targets native EVMYulLean +dispatcher execution. Lower transition evidence still records Verity's custom +Yul statement interpreter path through the EVMYulLean-backed builtin backend: ```lean interpretYulRuntimeWithBackend .evmYulLean ``` -That path proves the custom interpreter agrees with EVMYulLean-backed builtin -semantics for the bridged fragment. The final transition is complete only when -the public compiler-correctness theorem targets native EVMYulLean execution -directly, or an equivalent wrapper whose only execution engine is +The removed transition theorem name +`yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle` marks +the old shape: composing Layer 3 through the reference oracle before rewriting +to an EVMYulLean-backed builtin executor. The final transition is complete only +when the public compiler-correctness theorem targets native EVMYulLean +execution directly, or an equivalent wrapper whose only execution engine is `EvmYul.Yul.callDispatcher`. ## Current Baseline @@ -25,13 +28,17 @@ The current baseline is: - Layer 2 proves semantic preservation from supported `CompilationModel` programs to IR. -- Layer 3 proves IR-to-Yul preservation over Verity's custom statement - interpreter, retargeted to the `.evmYulLean` backend for builtin execution. -- `Compiler.Proofs.YulGeneration.Backends.Native.interpretRuntimeNative` and - `interpretIRRuntimeNative` execute through native EVMYulLean, but the generic - native-vs-interpreter agreement is still an explicit theorem seam. -- `simpleStorage_endToEnd_native_evmYulLean` is a concrete native theorem with - no public retrieve-hit, store-hit, or selector-miss bridge premises. +- Public EndToEnd proofs now target + `Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative`, + which executes through native EVMYulLean. Helper-free and mapping-helper + generated-dispatcher wrappers consume concrete dispatcher lowering and build + full emitted-runtime native lowering internally. +- Lower Layer 3 transition modules still contain isolated reference-oracle and + backend-wrapper evidence for the bridged fragment; that evidence is not the + public EndToEnd proof authority. +- `simpleStorage_endToEnd_native_evmYulLean` is a concrete native theorem over + the direct projected `EvmYul.Yul.callDispatcher` result, with no public + retrieve-hit, store-hit, or selector-miss bridge premises. - The active compiler stack has zero project-level Lean axioms and zero `sorry` placeholders. @@ -65,9 +72,9 @@ The transition is done only when all criteria in this section are true on - The theorem-facing native target is either `Native.interpretIRRuntimeNative` or a narrower wrapper that internally lowers to EVMYulLean and executes via `EvmYul.Yul.callDispatcher`. -- No public theorem keeps a generic native-vs-custom-interpreter agreement - premise such as `nativeIRRuntimeAgreesWithInterpreter`, - `nativeCallDispatcherAgreesWithInterpreter`, or an equivalent bridge +- No public theorem keeps a native-vs-custom-interpreter agreement premise such + as `nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper`, + `nativeCallDispatcherAgreesWithEvmYulLeanFuelWrapper`, or an equivalent bridge assumption. - Any remaining comparison with the custom interpreter is explicitly marked as regression or differential testing, not as the authoritative proof target. @@ -259,7 +266,7 @@ Current architecture: interpretYulRuntimeWithBackend .evmYulLean - This is Verity's custom fuel-based Yul interpreter with EVMYulLean-backed + This is Verity's custom Yul statement interpreter with EVMYulLean-backed builtin semantics. The native path exists through: Native.interpretRuntimeNative @@ -356,7 +363,7 @@ Before declaring the transition complete, verify these exact facts: ```bash ! rg "interpretYulRuntimeWithBackend \\.evmYulLean" Compiler/Proofs/EndToEnd.lean -! rg "nativeIRRuntimeAgreesWithInterpreter|nativeCallDispatcherAgreesWithInterpreter" Compiler/Proofs/EndToEnd.lean +! rg "nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper|nativeCallDispatcherAgreesWithEvmYulLeanFuelWrapper" Compiler/Proofs/EndToEnd.lean ! rg "\\bsorry\\b|\\badmit\\b|^axiom " Compiler Verity Contracts python3 scripts/check_axioms.py python3 scripts/generate_print_axioms.py --check diff --git a/docs/NATIVE_EVMYULLEAN_TRANSITION.md b/docs/NATIVE_EVMYULLEAN_TRANSITION.md index 525d89d32..c74d1d32c 100644 --- a/docs/NATIVE_EVMYULLEAN_TRANSITION.md +++ b/docs/NATIVE_EVMYULLEAN_TRANSITION.md @@ -9,7 +9,7 @@ The detailed completion contract and reusable agent prompt live in ## Current State -The current public proof path still targets: +The deeper generated-Yul preservation path still targets: ```lean interpretYulRuntimeWithBackend .evmYulLean @@ -41,30 +41,137 @@ materializes pre-state storage for those slots. - Native result projection preserves pre-existing event history and appends native EVMYulLean logs, matching the observable shape expected by the current proof-side `YulResult`. -- The EndToEnd layer now exposes the native-facing theorem seam - `layers2_3_ir_matches_native_evmYulLean_of_interpreter_bridge`. Its - conclusion targets `Native.interpretIRRuntimeNative` through - `nativeResultsMatchOn`, comparing success, return value, events, and the - explicitly observable final-storage slots, but it still requires the explicit - `nativeIRRuntimeAgreesWithInterpreter` obligation for the generated runtime. - That obligation is observable-slot and fuel-aligned with the native run through - `interpretYulRuntimeWithBackendFuel`, and the theorem seam currently requires - that fuel to equal the interpreter proof stack's default runtime fuel - `sizeOf (Compiler.emitYul contract).runtimeCode + 1`. This is the exact - remaining native-vs-interpreter equivalence theorem plus a named - full-storage-projection and fuel-parametric-preservation gap, not a completed - public flip. -- The same module also exposes - `nativeCallDispatcherAgreesWithInterpreter`, - `nativeDispatcherBlockAgreesWithInterpreter`, - `nativeCallDispatcherAgreesWithInterpreter_of_dispatcherBlock_agree`, - `nativeIRRuntimeAgreesWithInterpreter_of_lowered_callDispatcher_agree`, - `layer3_contract_preserves_semantics_native_of_lowered_callDispatcher_bridge`, +- The EndToEnd layer now exposes a small native result surface: + `nativeResultsMatchOn`, `sourceResultMatchesNativeOn`, the source/native + composition theorem over that result surface, + `nativeGeneratedCallDispatcherResultOf`, + `nativeGeneratedCallDispatcherMatchesIROn`, the supported-compiler + generated direct `EvmYul.Yul.callDispatcher` theorem + `compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match`, the + helper-free call-dispatcher lowering wrapper + `compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping`, + the mapping-helper call-dispatcher lowering wrapper + `compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping`, + and the concrete SimpleStorage native theorem. The dispatcher-exec + compatibility predicate and wrappers are file-local helpers; public generated + correctness exposes native `EvmYul.Yul.callDispatcher` premises and derives + source/native agreement directly over the projected call-dispatcher result. + The old generated runtime adapter wrappers have been removed rather than + being retained as file-local `interpretIRRuntimeNative` compatibility + theorems. On the + helper-free and mapping-helper paths, the public wrapper theorems still accept + the concrete generated-dispatcher lowering result while exposing the direct + projected `EvmYul.Yul.callDispatcher` result. The concrete SimpleStorage + native theorem now targets that direct projected call-dispatcher result too. + The opaque arbitrary-fuel + identity seams, generated dispatcher-exec lift facts, and fuel-indexed + `nativeIRRuntimeMatchesIR` targets are file-local, and the older + proof-interpreter bridge signature has been removed from EndToEnd. The public + generated target is native `EvmYul.Yul.callDispatcher` through + `nativeGeneratedCallDispatcherResultOf` and `nativeResultsMatchOn`, comparing + success, return value, events, and the explicitly observable final-storage + slots. The backend-parameterized safe-body Yul target is now isolated + lower-level transition evidence; the generated native fragment still needs + broader direct match proofs before that transition plumbing can be removed + completely. +- The same module also keeps file-local transition seams for + `nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_positive_match`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure_ofIR_environment`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure_ofIR_globalDefaults`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_eq_match`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_environment`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_globalDefaults`, + `layer3_contract_preserves_semantics_native_of_generated_dispatcherExec_positive_match`, + `layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_positive_external_bodies_match`, + `layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_positive_body_closure`, + `layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_external_bodies_match`, + `layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_body_closure`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_external_bodies_match`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_match`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_external_bodies_match`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_match`, + with `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure` + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure_ofIR_environment`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure_ofIR_globalDefaults`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_environment`, + and `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_globalDefaults` + as the explicitly named safe-body wrapper aliases. + The canonical native runtime and selected full-runtime wrapper surfaces set dispatcher fuel to + `nativeRuntimeDispatcherFuel irContract` and runtime fuel to + `nativeRuntimeFuel irContract`, avoiding an arbitrary public fuel parameter + on the recommended direct-match surface. These direct match seams keep the + remaining proof obligation at concrete native lowering, selected-path + environment validation, and either raw positive dispatcher-exec matching or + projected-result matching against IR execution. The compiled supported + fragment check is now named explicitly by + `generatedRuntimeNativeFragment_of_compile_ok_supported_safe` and + `validateGeneratedRuntimeNativeFragment_of_compile_ok_supported_safe`, so the + executable generated-runtime validator is closed from the same public + `SupportedSpec`, static-parameter, and safe-body hypotheses as the native + wrapper seams. Full generated-runtime native lowering success is named by + `lowerRuntimeContractNative_of_compile_ok_supported_exists`, directly + packaging `SupportedSpec + compile` into an executable + `lowerRuntimeContractNative` witness. The helper-free native lowering boundary is also named by + `lowerRuntimeContractNative_emitYul_noMapping_noInternals_noFallback_noReceive` + in the native harness and by + `lowerRuntimeContractNative_of_compile_ok_supported_noMapping` for compiled + supported contracts, reducing no-mapping runtimes to the single generated + dispatcher shell. The public + `compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping` + wrapper consumes that concrete dispatcher lowering directly, exposes the + generated `EvmYul.Yul.callDispatcher` result surface, and keeps the same full + emitted-runtime lowering equality internal. The mapping-helper side of + the same boundary is now named by `nativeMappingSlotFunctionDefinition` and + `lowerFunctionDefinitionNativeWithReserved_mappingSlotFuncAt_zero`, which + package the concrete native lowering of the generated `mappingSlot` helper at + scratch base zero. Mapping-enabled emitted runtime lowering is now packaged + by + `lowerRuntimeContractNative_emitYul_mapping_noInternals_noFallback_noReceive_reserved` + in the native harness and by + `lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved` for + compiled supported contracts, with the generated dispatcher lowered under the + full emitted-runtime reserved-name context. The public + `compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping` + wrapper consumes that reserved-context dispatcher lowering directly, keeps the + reserved-context emitted-runtime lowering internal, and exposes the generated + `EvmYul.Yul.callDispatcher` premise. Successful full native lowering + can now also be peeled back to the concrete dispatcher lowering by + `lowerRuntimeContractNative_emitYul_noMapping_ok_dispatcher`, + `lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher`, + `lowerRuntimeContractNative_emitYul_mapping_ok_dispatcher_reserved`, and + `lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved`. + The no-mapping positive/projected native wrappers + `nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping` and - `layers2_3_ir_matches_native_evmYulLean_of_lowered_callDispatcher_bridge`. - These move the remaining proof obligation down to concrete native lowering, - selected-path environment validation, and projected native dispatcher-block - execution agreement with the fuel-aligned interpreter oracle. + `nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping` + now consume the narrower dispatcher-statement lowering equality directly. The + `_ofIR_environment` and `_ofIR_globalDefaults` variants discharge the native + environment side condition for the same no-mapping dispatcher-statement shell, + while the matching + `layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_*` + and `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_*` + wrappers expose the direct native-vs-IR result surface. The mapping-enabled equivalents are + exposed under the + `_mapping_reserved` suffix for the `nativeIRRuntimeMatchesIR`, + `layer3_contract_preserves_semantics_native_of_compiled_generated_*`, and + `layers2_3_ir_matches_native_evmYulLean_of_generated_*` dispatcher-statement + wrapper families. The `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_*` + wrappers now compose successful full runtime lowering with those dispatcher + statement surfaces, so + callers can remain at the emitted-runtime lowering boundary while proving + the exact extracted dispatcher match. The same + full-runtime boundary is lifted to Layer 3 by the + `layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_*` + wrapper family, and to the Layers 2+3 composition by the + `layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_*` + wrapper family. The public Layers 2+3 full-runtime dispatcher-statement + wrappers also expose `_ofIR_environment` and `_ofIR_globalDefaults` variants for both no-mapping + and `_mapping_reserved` paths, matching the narrower dispatcher-statement + environment-discharge surface while keeping callers at the full + emitted-runtime lowering boundary. - The native harness also names the dispatcher-block execution that `EvmYul.Yul.callDispatcher` performs after fuel checking and empty call-frame setup: `callDispatcherBlockResult`, with @@ -88,6 +195,46 @@ materializes pre-state storage for those slots. `selectedSwitchBody_hit`, and `selectedSwitchBody_miss`. - The native harness remains separate from the existing retargeting theorem, so the proof tree does not claim a theorem that is not yet proved. +- The current private transition-only + `yulCodegen_preserves_semantics_evmYulLeanBackend` theorem still composes + through + `yulCodegen_preserves_semantics_via_reference_oracle` before rewriting the + emitted runtime to the private EVMYulLean backend executor wrapper + `interpretYulRuntimeWithBackend`. The explicit + `yulCodegen_preserves_semantics_evmYulLeanBackend` theorem gives isolated + transition evidence for an EVMYulLean-backed Yul target, but it is not yet a + native source-of-truth + Layer 3 proof. The older + `yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle` name + remains only as a private compatibility alias; public EndToEnd wrappers no + longer consume either legacy retarget name. +- The older generic native reference-oracle/fuel-wrapper aliases have been + removed. The remaining file-local native Layer 3 transition seams consume + `nativeIRRuntimeMatchesIR` directly, while the public supported EndToEnd + theorems expose direct `EvmYul.Yul.callDispatcher` results. The generated + native fragment's direct match proof remains the visible blocker for deleting + the private runtime transition layer. +- `nativeDispatcherExecMatchesIRPositive_of_project_eq_match` now gives the + remaining generated-dispatch proof a single projected-result introduction + form, so endpoint-specific native success/halt/error splits are only needed + when a proof needs endpoint-specific facts. +- `nativeIRRuntimeMatchesIR_of_lowered_dispatcherExec_project_eq_match` and + `nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_project_eq_match` + lift that projected-result package through the native runtime harness. +- The EndToEnd module mirrors that projected-result surface for compiled + supported contracts through + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_eq_match`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_environment`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_globalDefaults`, + and the `layer3_...project...` / `layers2_3_...project...` wrappers, so + callers can provide one projected native result equality plus the observable + match without first building the positive-dispatcher predicate. + The `_ofIR_environment` variants discharge raw native environment validation + from representable `tx.chainId`/`tx.blobBaseFee` facts plus the + selected-path unsupported-header check. The `_ofIR_globalDefaults` variants + package the current EVMYulLean global-default transaction case behind the + same selected-path unsupported-header check. ## Clean Target Architecture @@ -110,6 +257,172 @@ oracle, not as the semantic target in the public theorem stack. The following verified user reports should stay explicit in the transition scope so the native path does not look more complete than it is: +- The public supported generated `callDispatcher` theorem is now composed down + to native `EvmYul.Yul.callDispatcher`, with selector miss and generated + selector-hit guard failures discharged internally. The closed generic case + wrappers are + `nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_exists_of_compile_ok_supported`, + `nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_exists_of_compile_ok_supported`, + and + `nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_exists_of_compile_ok_supported`. + The artifact/error continuation path remains named by + `nativeGeneratedCallDispatcherResult_selector_hit_error_matchesIR_exists_of_compile_ok_supported`. + Its remaining success-path blocker is the selected user-body result boundary: + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel`. The normal-return side + still needs a generic native execution proof for + `NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived`, connecting the + lowered selected `fn.body` at dispatcher fuel to `execIRFunction`; the + halt-channel side is currently supplied by + `NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel`. The source-level + public composition theorem + `compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher` + now rewrites the generated dispatcher result to the canonical + `interpretIRRuntimeNative` target, packages that result with the source-to-IR + compiler theorem, and discharges the lowered native runtime witness + internally. The public IR/native theorem keeps the direct projected result + target. The public theorem no longer exposes full `DispatchGuardsSafe`; + `SupportedSpec` carries the selected function calldata-threshold inventory, and + `generatedFunctionCalldataThreshold_of_compile_ok_supported` transports that + inventory across `compile` to the generated IR function selected by the + dispatcher. Legacy premise-taking `compile_preserves_native_evmYulLean_*` + wrappers are file-local; the public `compile_preserves_native_evmYulLean_*` + surface is limited to the direct `nativeGeneratedCallDispatcherResultOf` + composition theorem and the generated `SupportedSpec + compile` composition + theorem. The private success bridge rebuilds `DispatchGuardsSafe` after + the generated value and argument guards have selected the success branch. + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mapping` + packages the mapping-helper straight-body preservation path through + `NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_bridgedStraightStmts`. + The no-mapping helper-free straight-body preservation bridge is now split + out as `NativeMappingFreeBridgedExpr`, + `NativeExprPreservesWord_lowerExprNative_of_mappingFreeBridgedExpr`, + `NativeMappingFreePreservableStraightStmt`, + `NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts`, + and + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_mappingFreePreservableStraightStmts`. + Historical `BridgedStraightStmts` no-mapping bodies can now enter that same + actual-runtime path through `NativeMappingFreeSideConditionForBridgedStraightStmt`, + `NativeMappingFreePreservableStraightStmts.of_bridgedStraightStmts`, and + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mappingFree`. + The dispatcher-level adapter + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree` + composes that result bridge with the supported `compile` theorem stack. + The compile-to-body handoff is tracked by + `generatedRuntimeSelectedFunctionBodyBridged_of_compile_ok_supported`, + `lowerStmtsNativeWithSwitchIds_selectedFunctionBody_exists_of_compile_ok_supported`, + `selectedFunctionBodyBridgedAndLowered_of_compile_ok_supported`, and + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_closure_of_compile_ok_supported`, + which packages the selected `BridgedStmts` witness, selected native-body + lowering success, and generated calldata-threshold fact from `SupportedSpec + + compile` without claiming native execution semantics. The dispatcher + artifact handoff remains tracked by + `nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_exists_of_compile_ok_supported`, + and + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_artifacts_of_compile_ok_supported` + combines those lowered artifacts with the selected-body closure facts for the + actual dispatcher-selected `fn.body`. When generated switch-case freshness is + available, + `selectedUserBodyClosureAndMatchedFresh_of_compile_ok_supported_switchFresh` + also strips the generated guard prefix and recovers matched-flag freshness + for the actual lowered user body. That freshness handoff still has to be + consumed before the selected-body preservation callback loses the current + `hLowerCases` fact: the later result-bridge callback only sees the selected + `hBodyLower`/`hUserBodyLower` pair, while switch-case freshness is stated over + the full lowered `cases'` list. The next adapter should therefore stay at the + dispatcher artifact boundary, or widen the preservation callback to carry + `hLowerCases`, instead of trying to reconstruct whole-case freshness from a + selected body lowering alone. The mapping-helper side now has that + dispatcher-boundary handoff under + `nativeGeneratedSelectorHitBodyPreservesMatched_mapping_of_switchFresh` and + `NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh`, + with + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh` + carrying it back to the generated dispatcher theorem, + mirroring the earlier mapping-free `switchFresh` adapter while keeping + mapping-specific straight-body side conditions private. + The dispatcher wrappers can now consume the smaller per-case lowering + freshness premise through + `nativeGeneratedSwitchTempsFreshForNativeBodies_of_case_body_fresh`, + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree_caseFresh`, + and + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_caseFresh`; + the remaining freshness work is to derive that per-case premise from the + generated straight-body shape and reserved-name set. + A fully closed + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_compile_ok_supported` + lemma is still missing. The proof cannot be completed from the current + handoff facts alone: the dispatcher-facing adapters also need the generic + selected-body execution predicate + `NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived`, straight-body + preservation inputs (`BridgedStraightStmts` plus the mapping/no-mapping side + conditions), and a lowered-body freshness proof showing the generated matched + flag is absent from `nativeStmtsWriteNames bodyNative`. The compile-supported + handoff currently gives `BridgedStmts fn.body` and successful native + lowering, but not those stronger execution, straight-fragment, side-condition, + or matched-temp freshness facts. + The normal-return execution side now has a sound singleton-`leave` base case: + `execIRStmts_single_leave_succ_succ`, + `exec_block_leave_ok_add_ten`, and + `NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body`. + This does not close the dispatcher result boundary because native `leave` + exits through a revivable checkpoint, so the existing matched-flag + preservation predicate is not the right continuation fact for that shape. + The halt-channel side now also has a singleton-`stop` base case: + `execIRFunction_single_stop`, `exec_block_stop_halt_add_ten`, and + `NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_stop_body`; it + composes through + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_stop_body` and + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_stop_body`. + The halt-channel scalar-return side now also covers literal external + returns via `execIRFunction_mstore0_lit_return32`, + `exec_lowerExprNative_mstore_lit_lit_ok_fuel`, + `NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_lit_return32`, + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_lit_return32`, + and + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_lit_return32`. + Single-argument external returns are covered by + `execIRFunction_mstore0_calldataload4_return32_of_args_cons`, + `exec_lowerExprNative_mstore_lit_calldataload_lit_ok_fuel`, + `NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload4_return32`, + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload4_return32`, + and + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload4_return32`. + The reusable aligned-calldata return seams are + `execIRFunction_mstore0_calldataload_aligned_return32`, + `initialState_calldataload_aligned_arg_word`, + `exec_lowerExprNative_mstore_lit_calldataload_lit_ok_fuel`, and + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload_aligned_return32` + under the explicit `ByteArray.readBytes` offset condition + `4 + 32 * idx < 2^64`. + The remaining normal-return blocker is the generic body-shape discovery path: + generated selected bodies still need to identify arbitrary scalar return + bodies and supply the mapping-free straight-body predicate automatically. A + direct source-shape handoff cannot simply reuse the raw two-statement exact + return lemmas, because `compileFunctionSpec` prepends `genParamLoads`; even + zero-parameter functions carry the generated calldata-size guard in + `fn.body`. The zero-parameter literal-return instance is now closed through + the guarded generated shape with + `NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_lit_return32`, + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_lit_return32`, + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_lit_return32`, + and the source-shape wrapper + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_lit_return32`. + The matching zero-parameter storage-return shape is closed with + `NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_sload0_return32`, + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_sload0_return32`, + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_sload0_return32`, + and + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_sload0_return32`. + The generated one-argument setter shape now also closes through the generated + parameter-load guard and `value` binding: + `execIRFunction_oneParam_store0_value_stop`, + `NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_oneParam_store0_value_stop`, + `NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_oneParam_store0_value_stop`, + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_oneParam_store0_value_stop`, + and + `nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_oneParam_store0_value_stop`, + with the source/native preservation wrapper + `compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher_source_oneParam_store0_value_stop`. - [#1741](https://github.com/lfglabs-dev/verity/issues/1741): `blockTimestamp` is bridged through native EVMYulLean execution, and native smoke coverage now checks `timestamp()`/`number()` state reads. Native @@ -122,10 +435,22 @@ scope so the native path does not look more complete than it is: not yet have Verity `YulTransaction` fields, such as `coinbase`, `difficulty`, `prevrandao`, `gaslimit`, `basefee`, and `gasprice`, also fail closed on the selected native runtime path instead of reading EVMYulLean's zeroed header - defaults. The native harness names the remaining unbridged boundary with + defaults. The account-balance builtin `selfbalance` also fails closed on the + selected native runtime path until the bridge carries Verity's `selfBalance` + into the EVMYulLean account map. The native harness names the remaining + unbridged boundary with `initialState_unbridgedEnvironmentDefaults`, pinning base-fee/blob fields and native `chainid` to their current EVMYulLean default/global behavior until - the follow-up widens the state bridge. The + the follow-up widens the state bridge. The helper theorems + `validateNativeRuntimeEnvironment_ofIR_representableEnvironment` and + `validateNativeRuntimeEnvironment_ofIR_globalDefaults` now package the common + `YulTransaction.ofIR` validation cases once selected-path unsupported header + builtin use has been ruled out. EndToEnd mirrors the global-default case with + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure_ofIR_globalDefaults`, + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_globalDefaults`, + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure_ofIR_globalDefaults`, + and `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_globalDefaults`. + The `verity_contract` surface now accepts monadic environment reads such as `let t <- blockTimestamp`, `let t <- Verity.blockTimestamp`, `blockNumber`, `chainid`, `blobbasefee`, `contractAddress`, `msgSender`, and `msgValue`, and the @@ -195,13 +520,11 @@ scope so the native path does not look more complete than it is: `callDispatcher_succ_eq_callDispatcherBlockResult` to the named `callDispatcherBlockResult`, then rewrites initial-state execution to `contractDispatcherBlockResult`, then peels the block wrapper to - `contractDispatcherExecResult`. EndToEnd exposes - `nativeDispatcherBlockAgreesWithInterpreter` plus - `nativeDispatcherExecAgreesWithInterpreter`, - `nativeDispatcherBlockAgreesWithInterpreter_of_exec_agree`, and - `nativeCallDispatcherAgreesWithInterpreter_of_dispatcherBlock_agree`. The - remaining bridge is therefore direct native `EvmYul.Yul.exec` execution of - the lowered contract dispatcher block against the interpreter oracle. + `contractDispatcherExecResult`. EndToEnd now exposes the direct + `nativeDispatcherExecMatchesIRPositive` target plus generated-shape lifts to + `nativeIRRuntimeMatchesIR`, so positive-fuel callers prove raw dispatcher + execution against IR directly instead of passing through intermediate + fuel-wrapper agreement predicates. Statement-level native lowering through `lowerStmtsNativeWithSwitchIds`/`lowerStmtGroupNativeWithSwitchIds` is now @@ -214,23 +537,23 @@ scope so the native path does not look more complete than it is: runs only when no case has marked the switch matched. The top-level partition equation and statement-level lowering equations are proved, but full dispatcher-block agreement still requires per-statement native execution - preservation lemmas against `execYulFuelWithBackend .evmYulLean`. - EndToEnd now provides raw-exec intro forms for the three concrete native - outcomes: - `nativeDispatcherExecAgreesWithInterpreter_of_exec_ok_agree`, - `nativeDispatcherExecAgreesWithInterpreter_of_exec_yulHalt_agree`, and - `nativeDispatcherExecAgreesWithInterpreter_of_exec_error_agree`. These let - each generated-statement simulation case finish from a proved + preservation lemmas against IR. EndToEnd provides raw-exec intro forms for + the direct native-vs-IR concrete outcomes: + `nativeDispatcherExecMatchesIRPositive_of_exec_ok_match`, + `nativeDispatcherExecMatchesIRPositive_of_exec_ok_project_eq_match`, + `nativeDispatcherExecMatchesIRPositive_of_exec_yulHalt_project_eq_match`, + and `nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match`. + These let each generated-statement simulation case finish from a proved `contractDispatcherExecResult` equation plus the corresponding observable - projection agreement. + projection match. The generated dispatcher selector expression is also pinned for the - EVMYulLean-backed interpreter oracle: - `bridgedExpr_selectorExpr` shows that `selectorExpr` is in the bridged - expression fragment, and - `evalYulExprWithBackend_evmYulLean_selectorExpr_semantics` proves that it - evaluates to `state.selector % selectorModulus`. This discharges the - interpreter-oracle side of the first selector branch condition. The native + EVMYulLean-backed EVMYulLean fuel wrapper: + the private `bridgedExpr_selectorExpr` lemma shows that `selectorExpr` is in + the bridged expression fragment, and the private + `evalYulExprWithBackend_evmYulLean_selectorExpr_semantics` lemma proves that + it evaluates to `state.selector % selectorModulus`. This discharges the + isolated interpreter-oracle side of the first selector branch condition. The native side now exposes `lowerExprNative_selectorExpr`, `step_calldataload_ok`, `step_shr_ok`, `primCall_calldataload_ok`, `primCall_shr_ok`, and @@ -305,7 +628,40 @@ scope so the native path does not look more complete than it is: `lowerSwitchCasesNativeWithSwitchIds_find?_some` and `lowerSwitchCasesNativeWithSwitchIds_find?_none`, proving that native case lowering preserves the source switch selector lookup result while exposing - the switch-temp counter interval for the selected lowered body. The + the switch-temp counter interval for the selected lowered body. The native + harness lifts those generic lookup facts to generated dispatcher function + lookup with `lowerSwitchCasesNativeWithSwitchIds_find?_some_of_find_function` + and `lowerSwitchCasesNativeWithSwitchIds_find?_none_of_find_function`, so an + `IRFunction` selector hit or miss now produces the corresponding lowered + native case lookup fact directly. It also exposes `buildSwitchSourceCases` + and `buildSwitchSourceCases_eq_switchCases`, plus the actual-`buildSwitch` + wrappers `lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_some_of_find_function` + and `lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function`, + so generated dispatcher proofs can consume the source case list emitted by + `Compiler.CodegenCommon.buildSwitch` without first rewriting manually to + `switchCases`. The native harness also owns + `lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative`, the generic + singleton non-`funcDef` runtime lowering boundary for dispatcher-only runtime + code. Helper-free emitted runtime lowering is packaged by + `lowerRuntimeContractNative_emitYul_noMapping_noInternals_noFallback_noReceive`. + It also owns the generic + block-lowering shape lemmas `lowerStmtsNative_single_block_ok_singleton` and + `lowerStmtsNative_block_stmts_eq`, plus the generated-dispatcher peel facts + `lowerStmtsNativeWithSwitchIds_let_head_eq`, + `lowerStmtsNativeWithSwitchIds_if_head_eq`, and + `lowerStmtsNativeWithSwitchIds_singleton_switch_eq`. That leaves the + concrete default-revert switch lowering facts + `lowerStmtsNativeWithSwitchIds_revert_zero_zero`, + `lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq`, and + `lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered` + in the native harness as well. The harness now also packages those peels for + the actual no-fallback/no-receive generated dispatcher in + `buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered`, with + `buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function` + and `buildSwitch_noFallback_noReceive_lowered_inner_find?_none_of_find_function` + further combining that generated shape with function-selector lookup facts. + This leaves the EndToEnd SimpleStorage dispatcher reduction as aliases over + native-harness facts. The remaining native dispatcher proof starts after that complete lazy-switch bridge, at proving `NativeBlockPreservesWord` for selected/default lowered bodies and threading the initialized prefix state plus the lowering lookup @@ -332,6 +688,12 @@ scope so the native path does not look more complete than it is: `NativeStmtPreservesWord_if_of_eval_self`, `NativeStmtPreservesWord_if_of_eval_preserves`, `NativeStmtPreservesWord_if_of_cond_preserves`, + `nativeSwitchBranchFold_ok_preserves_word`, + `execSwitchCases_ok_branch_preserves_word`, + `NativeStmtPreservesWord_switch_of_eval_preserves`, + `NativeStmtPreservesWord_switch_of_cond_preserves`, + `NativeStmtPreservesWord_switch_of_cond_preserves_and_nativeStmtsWriteNames_not_mem`, + `NativeStmtPreservesWord_switch_of_eval_preserves_and_nativeStmtsWriteNames_not_mem`, `NativeStmtPreservesWord_lowerAssignNative_lit_of_ne`, `NativeStmtPreservesWord_lowerAssignNative_hex_of_ne`, `NativeStmtPreservesWord_lowerAssignNative_ident_of_ne`, @@ -345,6 +707,8 @@ scope so the native path does not look more complete than it is: `NativeStmtPreservesWord_let_lowerExprNative_ident_of_not_mem`, `NativeStmtPreservesWord_let_prim_of_evalArgs_primCall_preserves`, `NativeStmtPreservesWord_let_user_of_evalArgs_call_preserves`, + `NativeStmtPreservesWord_let_prim_of_nativeEvalArgs_primCall_preserves`, + `NativeStmtPreservesWord_let_user_of_nativeEvalArgs_call_preserves`, `NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves`, `NativeStmtPreservesWord_let_lowerExprNative_call_userFunction_of_evalArgs_call_preserves`, `NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves`, @@ -431,41 +795,73 @@ scope so the native path does not look more complete than it is: `NativeExprPreservesWord_lowerExprNative_str`, `NativeExprPreservesWord_lowerExprNative_ident`, `NativeExprPreservesWord_call_prim_of_evalArgs_primCall_preserves`, + `NativeExprPreservesWord_call_prim_of_nativeEvalArgs_primCall_preserves`, `NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves`, + `NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves`, `NativeExprPreservesWord_call_user_of_evalArgs_call_preserves`, + `NativeExprPreservesWord_call_user_of_nativeEvalArgs_call_preserves`, `NativeExprPreservesWord_lowerExprNative_call_userFunction_of_evalArgs_call_preserves`, + `NativeExprPreservesWord_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves`, `NativeStmtPreservesWord_exprStmtCall_prim_of_evalArgs_primCall_preserves`, `NativeStmtPreservesWord_exprStmtCall_user_of_evalArgs_call_preserves`, + `NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves`, + `NativeStmtPreservesWord_exprStmtCall_user_of_nativeEvalArgs_call_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_userFunction_of_evalArgs_call_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves`, `NativeStmtPreservesWord_exprStmtCall_mstore_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_mstore_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_mstore8_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_mstore8_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_sstore_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_sstore_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_tstore_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_tstore_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_log0_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_log0_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_log1_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_log1_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_log2_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_log2_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_log3_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_log3_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_log4_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_log4_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_return_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_return_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_revert_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_revert_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_evalArgs_preserves`, + `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_nativeEvalArgs_and_evalArgs_shape_preserves`, `NativeStmtPreservesWord_exprStmtCall_stop`, `NativeStmtPreservesWord_exprStmtCall_lowerExprNative_stop`, `nativeStmtWriteNames_not_mem_of_nativeStmtsWriteNames_not_mem`, @@ -630,6 +1026,33 @@ scope so the native path does not look more complete than it is: `exec_nativeSwitchCaseIfs_find_hit_fuel`, and `exec_nativeSwitchCaseIfs_find_none_fuel` for selector-lookup-driven case chain execution, + `lowerSwitchCasesNativeWithSwitchIds_find?_some_of_find_function` and + `lowerSwitchCasesNativeWithSwitchIds_find?_none_of_find_function` for + generated dispatcher function-lookup facts lifted through native case + lowering, + `buildSwitchSourceCases_eq_switchCases`, + `lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_some_of_find_function`, + and `lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function` + for the actual `buildSwitch` source case list, + `lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative` for singleton + dispatcher-only runtime lowering, + `lowerRuntimeContractNative_emitYul_noMapping_noInternals_noFallback_noReceive` + for helper-free emitted runtime lowering, + `lowerStmtsNative_single_block_ok_singleton` and + `lowerStmtsNative_block_stmts_eq` for generic `.block` lowering shape, + `lowerStmtsNativeWithSwitchIds_let_head_eq`, + `lowerStmtsNativeWithSwitchIds_if_head_eq`, and + `lowerStmtsNativeWithSwitchIds_singleton_switch_eq` for generic dispatcher + statement peels, + `lowerStmtsNativeWithSwitchIds_revert_zero_zero`, + `lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq`, and + `lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered` + for generated selector-miss default-revert lowering, + `buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered` for the + combined no-fallback/no-receive generated dispatcher lowering shape, + `buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function` + and `buildSwitch_noFallback_noReceive_lowered_inner_find?_none_of_find_function` + for generated dispatcher shape plus selector lookup, `exec_nativeSwitchDefaultIf_unmatched_nonempty_fuel` and `exec_nativeSwitchDefaultIf_matched_fuel` for optional generated defaults, `exec_block_append_ok`, @@ -653,9 +1076,9 @@ scope so the native path does not look more complete than it is: `nativeSwitchTempsFreshForNativeBodies`, plus freshness projection lemmas for selected native bodies and optional defaults, plus the named - `bridgedExpr_selectorExpr` and + private `bridgedExpr_selectorExpr` and `evalYulExprWithBackend_evmYulLean_selectorExpr_semantics` lemmas for the - generated dispatcher selector expression on the interpreter-oracle side, the named + generated dispatcher selector expression on the isolated interpreter-oracle side, the named `initialState_unbridgedEnvironmentDefaults` lemma for base-fee/blob-field defaults and native-global `chainid` behavior, callvalue, caller/address, calldatasize, timestamp/number, a native-vs-reference-oracle @@ -728,46 +1151,71 @@ scope so the native path does not look more complete than it is: - static-call permission behavior, - proof-level preservation for the covered mapping member oracle cases. -5. Introduce the public native preservation theorem. +5. Introduce the public generated native preservation theorem. - The EndToEnd module now has a named native theorem seam: + The EndToEnd module keeps the arbitrary-fuel identity seam private. The + file-local generated native theorem chain starts at: ```lean - layers2_3_ir_matches_native_evmYulLean_of_interpreter_bridge - ``` - - It targets `Native.interpretIRRuntimeNative` directly, but only under: - - ```lean - nativeIRRuntimeAgreesWithInterpreter fuel irContract tx initialState - observableSlots - ``` - - The next theorem in that chain is: - - ```lean - layers2_3_ir_matches_native_evmYulLean_of_lowered_callDispatcher_bridge + layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_match ``` It replaces the opaque bridge hypothesis with successful `lowerRuntimeContractNative`, successful `validateNativeRuntimeEnvironment`, and - `nativeCallDispatcherAgreesWithInterpreter` for the lowered native contract. - That obligation can now be discharged from - `nativeDispatcherBlockAgreesWithInterpreter`, which compares projected - `contractDispatcherBlockResult` execution with the interpreter oracle. - The block obligation can in turn be discharged from - `nativeDispatcherExecAgreesWithInterpreter`, which targets raw - `contractDispatcherExecResult`. - - This makes the remaining proof obligation concrete: for the supported - generated fragment, native `lowerRuntimeContractNative` plus - `EvmYul.Yul.exec` of the lowered contract dispatcher block must produce the - same projected `YulResult` as the current - `interpretYulRuntimeWithBackend .evmYulLean` interpreter oracle. The - successor theorem should discharge that bridge, or target a total native - wrapper once the remaining closed-failure cases are ruled out by syntactic - invariants. + `nativeDispatcherExecMatchesIRPositive` for the lowered native contract, plus + generated-code shape facts that discharge the executable generated-fragment + check. + The compiled supported path has a direct source-body-closure wrapper: + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure`. + This variant derives the external no-`funcDef` generated-fragment witness + from source-level static-scalar parameter witnesses plus compiled statement-list + no-`funcDef` closure, leaving the native dispatcher match itself as the + remaining proof obligation. + The concrete `simpleStorage_endToEnd_native_evmYulLean` theorem now targets + the direct projected `EvmYul.Yul.callDispatcher` result through + `nativeGeneratedCallDispatcherResultOf`, after its retrieve-hit, store-hit, + and selector-miss cases prove the lowered native dispatcher result matches + `interpretIR` directly. The older `interpretIRRuntimeNative` SimpleStorage + wrapper is file-local compatibility evidence. The generic selector-miss + boundary is now + packaged by + `exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq`, + which exposes the native `Revert` execution and exact projected rollback + result for arbitrary generated selector tables whose tags fit in one EVM + word. The same miss package is also lifted to the public raw dispatcher + boundary by + `contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq`. + Selector-hit native halt/error projection now has the analogous + generic boundary + `exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq`, + with + `contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq` + lifting that package to the public raw dispatcher boundary, + consumed by the SimpleStorage store-hit and retrieve-hit wrappers before + their contract-specific IR comparisons. The store-parametric + `exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq` + variant carries the same projection package through selector switches + entered after earlier dispatcher-local bindings. The store-parametric + selector-miss companion + `exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_projectResult_eq` + carries the exact revert rollback package through the same pre-bound local + store shape, and + `exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_projectResult_eq` + lifts it through the generated dispatcher block shape after + `__has_selector` is installed. Selector-hit halt/error projection has the + matching block-level package + `exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq`. + Selector-hit normal-success projection is carried by + `exec_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq`, + `exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq` + and + `exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq`. + + This closes the SimpleStorage public theorem against the native + lowered-dispatcher source of truth. The remaining generic work is to remove + the private compatibility fuel-wrapper/reference-oracle theorem family that + still exists for contracts without direct native dispatcher match proofs. A clean intermediate theorem is: @@ -782,18 +1230,283 @@ scope so the native path does not look more complete than it is: 6. Flip the trust boundary only after the theorem target moves. - Documentation should say EVMYulLean is the authoritative semantic target - only after the public theorem no longer routes through - `execYulFuelWithBackend`. Until then, the accurate status is: - EVMYulLean-backed builtin bridge proven, native runtime harness executable, - native public theorem pending. + Documentation should say EVMYulLean is the authoritative public semantic + target, while making clear that retargeting evidence remains isolated in + `EvmYulLeanRetarget.lean` and still routes through the private + `execYulFuelWithBackend` transition executor until the generic native proof + stack replaces it. + + The direct native target is now named `nativeIRRuntimeMatchesIR`: it compares + `Native.interpretIRRuntimeNative` against `interpretIR` on the observable + result surface. Remaining generated-fragment work can target a successful + native run plus `nativeResultsMatchOn` against IR directly. The Layer 3 and + Layers 2-3 native theorem spellings now consume `nativeIRRuntimeMatchesIR`; + the older `_via_reference_oracle` native wrapper variants have been removed. + At the raw lowered-dispatcher boundary, + `nativeDispatcherExecMatchesIRPositive` and + `nativeIRRuntimeMatchesIR_of_lowered_dispatcherExec_positive_match` expose the + same direct native-vs-IR target for positive-fuel generated dispatcher + proofs from the native harness. Concrete case proofs can now package normal, + projected halt, and projected error runs with + `nativeDispatcherExecMatchesIRPositive_of_exec_ok_match`, + `nativeDispatcherExecMatchesIRPositive_of_exec_ok_project_eq_match`, + `nativeDispatcherExecMatchesIRPositive_of_exec_yulHalt_project_eq_match`, and + `nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match`. + Generated-code shape facts lift this target through + `nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_positive_match`, + and compiled supported contracts can use + `nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure` + or the Layer 3 / Layers 2-3 wrappers + `layer3_contract_preserves_semantics_native_of_generated_dispatcherExec_positive_match` + and + `layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_match`. + Normal selector-hit execution has the matching raw dispatcher lift + `contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq`. + SimpleStorage now keeps only the direct per-case splitter + `simpleStorageNativeCallDispatcherMatchBridge_of_per_case` in this bridge + path. The public `simpleStorage_endToEnd_native_evmYulLean` theorem consumes + the direct projected `EvmYul.Yul.callDispatcher` result and discharges its + native match with this direct splitter. The + selector-miss revert arm is discharged by + `exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq` + and its contract-dispatcher boundary lift + `contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq` + (with + `exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_projectResult_eq` + and + `exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_projectResult_eq` + available for pre-bound dispatcher-local stores) + before the SimpleStorage-specific selector table specialization reaches + `simpleStorageNativeSelectorMissMatchBridge_proved`, and the retrieve-hit + and store-hit selector wrappers consume + `exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq` + (with + `exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq` + and + `exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq` + available at the generated dispatcher block boundary) + before their direct native-vs-IR proofs. The retrieve-hit arm has the proof + `simpleStorageNativeRetrieveHitMatchBridge_proved`. The store-hit arm is + closed by `simpleStorageNativeStoreHitMatchBridge_proved`, which covers both + the short-calldata revert and argument-present storage update paths. ## Cleanup After the Flip -- Move `execYulFuel` and `execYulFuelWithBackend` to reference-oracle status. +- Keep `legacyExecYulFuel` and the private `execYulFuelWithBackend` wrapper in + reference-oracle or isolated lower-level transition status. - Remove bridge-only docs that describe the custom interpreter as the active semantic target. - Keep cross-check tests between the old oracle and native EVMYulLean for one release cycle. - Upstream any EVMYulLean fork changes needed for memory, returndata, logs, or external-call semantics. + +## PR 1822 — Achievement Summary + +PR 1822 (`native-evmyullean-public-correctness`) lands the public-surface +retarget plus the first five leaf `ExecOnlyBridgeAtFuelRevived` constructors. +The Revived family now covers the observational-no-op body shapes a real +dispatcher will emit for label-only user bodies. The deeper "straight prefix +ending in `leave`/fall-through" cases are scoped out to a follow-up PR. + +### Shipped in this PR + +- **Public-surface retarget** — `interpretYulRuntimeEvmYulLean` and + `interpretYulRuntimeEvmYulLeanFuel`; Layer 3 and SimpleStorage EndToEnd + theorems retargeted to EVMYulLean conclusions; legacy reference-oracle + paths renamed to `..._via_reference_oracle`; `defaultBuiltinBackend := .evmYulLean`; + `legacyBuiltinBackend := .verity`, `legacyEvalBuiltinCallWithContext`, + `legacyExecYulFuel` opt-ins for old reference-oracle/bridge-comparison paths. +- **Native EndToEnd surface** — `nativeResultsMatchOn`, the supported-compiler + generated direct `EvmYul.Yul.callDispatcher` theorem and its helper-free / + mapping-helper lowering wrappers, concrete SimpleStorage native theorem, + case freshness dispatcher adapters, mapping switch freshness wrappers. +- **G1 increments S1–S4 (leaf Revived constructors)** — + `.of_block_empty`, `.of_block_leave`, `.of_singleton_comment` shipped on + `NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived`, plus the + pre-existing `.of_empty_body` and `.of_leave_body`. `.of_comment_cons` is + intentionally deferred to the success-bridge wiring layer (rationale below). + Together these five constructors cover every body of shape `[]`, `[.leave]`, + `[.block []]`, `[.block [.leave]]`, `[.comment text]` — the full + observational-no-op family. +- **Supporting harness lemmas** — `exec_block_block_nil_ok_add_ten`, + `exec_block_block_leave_ok_add_ten`, `exec_block_noop_block_head_eq`, + `lowerStmtsNativeWithSwitchIds_comment_head_eq`, and the source-side + `nativeResultsMatchOn_execIRFunction_*_body_markedPrefix` family. +- **Invariants preserved** — zero `sorry`, zero new axioms; `lake build + Compiler.Proofs.EndToEnd` green; `make check` validators (axioms, + capability boundary, builtin boundary, doc check) pass. + +### Remaining for a follow-up PR + +The composite `` and `; leave` body shapes, +and the final wiring + premise drop, are deferred. They share heavy proof +infrastructure (whole-block per-slot preservation, IR `execIRStmts` +falling-through induction) that does not fit a single landable increment in +the current branch's budget. See the +[G1 Incremental Plan](#g1-incremental-plan-generic-execonlybridgeatfuelrevived) +below for the exact constructor signatures, harness lemmas, and proof +sketches that the follow-up PR needs to land: + +- **G1-S5** `.of_nativePreservableStraightStmts_leave` plus companion + `execIRStmts_continue_of_nativePreservableStraightStmts_pre_leave` lemma. +- **G1-S6** `.of_bridgedStraightStmts_falling_through` (the deepest case; + requires aligning `execIRFunction`'s fall-through extraction with the + dispatcher's outer block exit). +- **G1-S7** Wire all five shipped leaves plus the two new constructors + through `NativeGeneratedSelectorHitSuccessBridge` adapters, including + per-leaf `_with_label_prefix` variants that strip a leading + `.comment "label"` head via `exec_block_noop_block_head_eq`. This step + also subsumes the deferred `.of_comment_cons` shape. +- **G1-S8** Drop `hUserBodyHalt` from + `compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher` + once S5–S7 are in. + +## G1 Incremental Plan: Generic `ExecOnlyBridgeAtFuelRevived` + +The remaining success-side blocker is a generic constructor for +`NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived` that does not +enumerate every concrete `fn.body` shape. The Revived predicate covers +**non-halting** bodies; halting bodies (`stop`/`return`/`revert`) are owned by +`NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel`, which already has a full +shape family. + +Today only two Revived constructors exist: +`NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_empty_body` +(`fn.body = []`) and `.of_leave_body` (`fn.body = [.leave]`). The remaining +Revived family is planned as a pyramid of independently-pushable +constructors, each of which compiles green on its own and is independently +useful to downstream adapters: + +1. **`.of_block_empty`** — `fn.body = [.block []]`. Lowers to + `[.Block []]`; closed by `exec_block_noop_block_head_eq` and + `exec_block_nil_ok`. Source-side `execIRFunction` collapses the inner empty + block to `.continue stateWithParams`, mirroring `.of_empty_body`. Needs a + companion `nativeResultsMatchOn_execIRFunction_block_empty_markedPrefix` + lemma. +2. **`.of_block_leave`** — `fn.body = [.block [.leave]]`. Lowers to + `[.Block [.Leave]]`; closed by `exec_block_leave_ok_add_ten` after a + `Block`-head peel. Mirrors `.of_leave_body`. +3. **`.of_singleton_comment`** — `fn.body = [.comment text]`. Lowers to + `[.Block []]` via `lowerStmtsNativeWithSwitchIds_comment_head_eq`. Source + side is `.continue state` (comment is a no-op at positive fuel). +4. **`.of_comment_cons`** — recursive adapter: if the tail satisfies the + Revived predicate then so does `.comment text :: rest`. Discharges the + no-op head with `exec_block_noop_block_head_eq` and matches the source-side + `.continue` step. + *Deferred to S8 wiring.* A direct Revived-level recursion is structurally + awkward because the Revived predicate's `nativeGeneratedSelectorHitUserBodyFuel` + computation depends on the contract's full `fn.body` size; recursing into + `rest` would require either a predicate-level refactor that parameterizes + over an explicit body shape, or full duplication of the predicate's logic + inline. Instead, the runtime dispatcher's `.comment "label" :: ` + shape is handled at the `NativeGeneratedSelectorHitSuccessBridge` wiring + layer (step 7): each leaf Revived constructor pairs with a one-shot + comment-prefix adapter that strips the no-op label head, leaving the + `` to match an existing leaf constructor. +5. **`.of_nativePreservableStraightStmts_leave`** — bodies of shape + `; leave`. Composes `NativePreservableStraightStmts` + preservation + (`NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_nativePreservableStraightStmts`) + with the `leave` checkpoint, yielding a `final.reviveJump` whose observable + slots equal the source-side post-state. Requires an + `execIRStmts_continue_of_nativePreservableStraightStmts_pre_leave` companion + lemma in `IRInterpreter.lean` proving the source side falls through with the + same observable storage. +6. **`.of_bridgedStraightStmts_falling_through`** — bodies of shape + `` (no terminator). The hardest piece: requires the source + side's `execIRStmts` falling through to `.continue` with native-side + `NativeBlockPreservesWord` preservation, combined with the function-end + fall-through convention shared between `execIRFunction` and `EvmYul.Yul.exec`. +7. **Wire into `NativeGeneratedSelectorHitSuccessBridge`** — extend + `NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_*` + adapters so the new Revived constructors feed the existing + `BridgedStraightStmts` and `mappingFree` result-bridge composition stacks. +8. **Drop the `hUserBodyHalt` premise from the supported-generated + call-dispatcher composition theorem** — once the Revived family covers the + same source-level scope as the Halt family, the public theorem premise + collapses. + +Each step lands as its own commit on `native-evmyullean-public-correctness` +and keeps `lake build Compiler.Proofs.EndToEnd` green. The pyramid is designed +so that partial completion (e.g., stopping after step 4) already removes +specific `hUserBodyHalt` demand for trivially-non-halting bodies, even before +the deep generic case at step 6 lands. + +### Status of G1 increments + +- **Step 1 (`.of_block_empty`)** — **shipped in PR 1822** + (commit `fa980235`+rebase `8b46a6e7`). Pairs with new harness lemma + `exec_block_block_nil_ok_add_ten` and source helper + `nativeResultsMatchOn_execIRFunction_block_empty_body_markedPrefix`. +- **Step 2 (`.of_block_leave`)** — **shipped in PR 1822** (`a5d2e0d3`). + Harness: `exec_block_block_leave_ok_add_ten`. Source helper: + `nativeResultsMatchOn_execIRFunction_block_leave_body_markedPrefix`. +- **Step 3 (`.of_singleton_comment`)** — **shipped in PR 1822** + (`f69044a1`+rebase `06723c83`). Reuses `exec_block_block_nil_ok_add_ten`; + existential text extraction in the hypothesis. Source helper: + `nativeResultsMatchOn_execIRFunction_singleton_comment_body_markedPrefix`. +- **Step 4 (`.of_comment_cons`)** — **intentionally deferred to step 7 + wiring** (`8e31e756`). Rationale: structural mismatch between the + predicate's `nativeGeneratedSelectorHitUserBodyFuel`-on-full-`fn.body` + and a tail-body recursion. Handled at the success-bridge layer via + per-leaf comment-prefix adapters (S7), not as a standalone Revived + constructor. +- **Step 5 (`.of_nativePreservableStraightStmts_leave`)** — **deferred to + follow-up PR**. + Companion lemma sketch: + ``` + theorem execIRStmts_continue_of_nativePreservableStraightStmts_pre_leave + (fuel : Nat) (state : IRState) (preStmts : List YulStmt) + (hStmts : NativePreservableStraightStmts preStmts) + (hFuel : sizeOf preStmts < fuel) : + ∃ state', + execIRStmts fuel state preStmts = .continue state' ∧ + ∀ slot, state'.storage.getD slot 0 = state.storage.getD slot 0 ∧ + state'.events = state.events + ``` + Proof by induction on `preStmts` (or on the `NativePreservableStraightStmts` + predicate) using the per-constructor cases in + `EvmYulLeanNativeHarness.lean` lines ~18395–18410. + Constructor sketch: the lowered native body is + `lower(preStmts) ++ [.Leave]`; dispatcher-wrapped as + `.Block (lower(preStmts) ++ [.Leave])`. Use + `exec_block_append_eq_of_continue` (or similar splice lemma) to split exec + across the append, derive `NativeBlockPreservesWord` for each observable + slot via `NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_nativePreservableStraightStmts`, + then peel the trailing `.Leave` with `exec_block_leave_ok_add_ten` after + one cons step. +- **Step 6 (`.of_bridgedStraightStmts_falling_through`)** — **deferred to + follow-up PR**. Hardest piece. Same machinery as step 5 minus the trailing leave: the + function-end fall-through convention must align `execIRFunction`'s + post-`execIRStmts` extraction with the dispatcher's outer block exit. Key + delta: source side returns `.continue state'` with no explicit terminator; + must show this projects observationally identical to native's + `.Block lower(preStmts)` `.ok` exit. Likely also needs an + `execIRFunction_continue_extract_eq` lemma showing the IR function's return + extraction at no-return-vars fn is a no-op. +- **Step 7 (success-bridge wiring + `.of_comment_cons` collapse)** — + **deferred to follow-up PR**. Extend + `NativeGeneratedSelectorHitSuccessBridge.of_selected_*` adapters to take + per-leaf Revived constructors and inject the `.comment "label"`-head strip + via `exec_block_noop_block_head_eq`. Each leaf gets a `_with_label_prefix` + variant. +- **Step 8 (drop `hUserBodyHalt`)** — **deferred to follow-up PR**. Final + theorem-level + collapse: after the Revived family covers all source-side non-halting + bodies the dispatcher can emit, the + `compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher` + signature drops its `hUserBodyHalt` premise. + +The PR-1822 shipped constructors (Step 1–3, plus the pre-existing +`.of_empty_body` and `.of_leave_body`) are independently useful: they +directly discharge the Revived premise for contracts whose selected +`fn.body` is one of `[]`, `[.leave]`, `[.block []]`, `[.block [.leave]]`, or +`[.comment text]`. This is the observational-no-op family — concrete +contracts whose user body is a label-only stub now have a direct Revived +bridge without going through the halt path. + +Steps 5–8 remain the path to dropping `hUserBodyHalt` for non-trivial user +bodies. A future PR should pick up `execIRStmts_continue_of_nativePreservableStraightStmts_pre_leave` +first (purely IR-side, no harness coupling) before tackling the full +constructor proofs. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index ed3abe1b0..66942ff36 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -240,8 +240,8 @@ Execution priorities: - `bridgedBuiltins` definition enumerates all 36 builtins where `.evmYulLean` and `.verity` backends agree - Unbridged: none; `mappingSlot` is bridged via the shared keccak-faithful `abstractMappingSlot` derivation - Phase 2 state bridge scaffolding: type conversions, storage round-trip, env field bridges (0 sorry) -- **Phase 4 (safe-body EndToEnd retarget)**: `EvmYulLeanRetarget.lean` proves `backends_agree_on_bridged_builtins` and `evalYulExpr_evmYulLean_eq_on_bridged`, establishing that `.verity` and `.evmYulLean` agree for `BridgedExpr` expressions built from bridged builtin calls plus backend-independent `tload`/`mload`. It also defines `execYulFuelWithBackend`, proves `execYulFuelWithBackend_verity_eq`, proves straight-line/block/if/switch/for statement-fragment helpers, proves `execYulFuelWithBackend_eq_on_bridged_target` for recursive `BridgedTarget` values, proves `emitYul_runtimeCode_bridged`, proves `emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies`, and proves `yulCodegen_preserves_semantics_evmYulLean`: the existing Layer-3 IR→Yul preservation theorem retargeted to `interpretYulRuntimeWithBackend .evmYulLean` under bridged-body hypotheses. `EndToEnd.lean` now exposes `layers2_3_ir_matches_yul_evmYulLean` over that EVMYulLean-backed target without raw external function-body `BridgedStmts` hypotheses, deriving them from `SupportedSpec`, static-parameter witnesses, and `BridgedSafeStmts` source-body witnesses. `EvmYulLeanBodyClosure.lean` proves universal `compileStmtList_always_bridged` coverage for `BridgedSafeStmts`; the external-call family remains carved out behind explicit function-table simulation work. `EvmYulLeanSourceExprClosure.lean` proves scalar leaf closure (`compileExpr_bridgedSource_leaf`) and pure arithmetic/comparison/bit-operation expression closure (`compileExpr_bridgedSource`) for the `BridgedSourceExpr` fragment. Trust boundary shifts for bridged expressions, recursive bridged statement targets, Layer-3 contract executions, and the safe-body EndToEnd wrapper with fully proven builtin dependencies. -- **Native runtime follow-up (#1737)**: the public theorem target still routes through the backend-parameterized Verity Yul interpreter. `EvmYulLeanNativeHarness.lean` provides the executable native path through `EvmYul.Yul.callDispatcher`, and `docs/NATIVE_EVMYULLEAN_TRANSITION.md` tracks the remaining state/result bridge lemmas and theorem flip needed to remove the custom interpreter from the public semantic target. +- **Phase 4 (safe-body EndToEnd retarget)**: `EvmYulLeanRetarget.lean` privately proves `backends_agree_on_bridged_builtins` and `evalYulExpr_evmYulLean_eq_on_bridged`, establishing isolated transition evidence that `.verity` and `.evmYulLean` agree for `BridgedExpr` expressions built from bridged builtin calls plus backend-independent `tload`/`mload`. It also privately defines `execYulFuelWithBackend`, privately proves `execYulFuelWithBackend_verity_eq`, the straight-line/block/if/switch/for statement-fragment helpers, `execYulFuelWithBackend_eq_on_bridged_target`, `emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies`, and the backend-wrapper codegen retarget facts. These remain isolated lower-level transition evidence rather than public proof authority, including the generated-runtime closure witnesses. `EvmYulLeanBodyClosure.lean` proves universal `compileStmtList_always_bridged` coverage for `BridgedSafeStmts`; the external-call family remains carved out behind explicit function-table simulation work. `EvmYulLeanSourceExprClosure.lean` proves scalar leaf closure (`compileExpr_bridgedSource_leaf`) and source-expression closure (`compileExpr_bridgedSource`) for arithmetic/comparison/bit-operation expressions, parameter length identifiers, storage, storage-array length, and ADT tag/field reads whose field lookup succeeds, singleton and nested mapping reads (`mapping`, `mappingWord`, `mappingUint`, `mapping2`, `mapping2Word`) through the abstract `mappingSlot` bridge, mapping struct-member reads (`structMember`, `structMember2`), the reserved exponentiation builtin surface, calldata/memory/transient reads, and syntactic `keccak256(offset, size)` emission in the `BridgedSourceExpr` fragment, with `compileExpr_keccak256_bridgedSource_of_exprCompileCore` exposing the compile-core argument case directly and `compileExpr_mappingChain_bridgedSource` covering `mappingChain` through the same abstract `mappingSlot` boundary. `mappingSlot` remains an abstraction boundary for mapping-slot memory+keccak equivalence, while `keccak256` remains a source-semantics boundary for full end-to-end expression correctness until the source evaluator models memory-slice hashing. `EvmYulLeanBodyClosure.lean` also packages singleton `let`/`assign` bindings of syntactic `keccak256(offset, size)` into `BridgedSafeStmts` via `bridgedSafeStmts_letKeccak_of_exprCompileCore` and `bridgedSafeStmts_assignKeccak_of_exprCompileCore`, plus the external two-statement memory-preimage shape via `bridgedSafeStmts_externalMstoreLetKeccak_of_exprCompileCore`. +- **Native runtime follow-up (#1737)**: `EvmYulLeanNativeHarness.lean` provides the executable native path through `EvmYul.Yul.callDispatcher`; `EndToEnd.lean` keeps the public theorem seams on the native result surface (`nativeResultsMatchOn` / `sourceResultMatchesNativeOn`), the generated direct call-dispatcher `compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match` theorem, the helper-free call-dispatcher lowering wrapper `compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping`, the mapping-helper call-dispatcher lowering wrapper `compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping`, and the concrete SimpleStorage native theorem. The public call-dispatcher and SimpleStorage native theorems expose source/native obligations directly over projected `EvmYul.Yul.callDispatcher` results; the older generated dispatcher-exec/runtime adapter wrappers have been removed from `EndToEnd.lean`. The no-mapping and mapping call-dispatcher wrappers still accept concrete generated-dispatcher lowering results while exposing the direct projected `EvmYul.Yul.callDispatcher` result. `docs/NATIVE_EVMYULLEAN_TRANSITION.md` tracks the remaining state/result bridge lemmas and theorem work needed to retire the isolated lower-level retargeting evidence completely. - **Remaining to make retargeting whole-program**: extend `BridgedSafeStmts` or add a separate function-table simulation for the external-call family (`internalCall`, `internalCallAssign`, `externalCallBind`, and `ecm`) **EVM Semantics**: Mitigated by differential testing against actual EVM execution (Foundry). Likely remains a documented fundamental assumption. diff --git a/docs/VERIFICATION_STATUS.md b/docs/VERIFICATION_STATUS.md index 37cfc7b54..325b248b3 100644 --- a/docs/VERIFICATION_STATUS.md +++ b/docs/VERIFICATION_STATUS.md @@ -79,7 +79,7 @@ Tracking: - Generic: supported statement-list compilation and the whole-contract theorem itself - Proved generically: initial-state normalization between `withTransactionContext` and `initialIRStateForTx`, under explicit transaction-context normalization hypotheses - No Lean axioms remain in Layer 2; 0 `sorry` placeholders remain. The `storageLookup_projectStorage` proof (previously a sorry) is now complete, using `Batteries.RBMap.find?_insert` lemmas with an injectivity argument over in-range storage slots. -- 6 stateful environment-reading builtins now have bridge proofs connecting Verity's `evalBuiltinCallWithContext` to the EVMYulLean state constructed by `toSharedState`: `callvalue`, `timestamp`, `number`, `caller` (requires valid address hypothesis), `address` (requires valid address hypothesis), and `calldatasize` (now reduced into UInt256 word semantics, so no extra size bound is needed) +- 6 stateful environment-reading builtins now have bridge proofs connecting Verity's `legacyEvalBuiltinCallWithContext` to the EVMYulLean state constructed by `toSharedState`: `callvalue`, `timestamp`, `number`, `caller` (requires valid address hypothesis), `address` (requires valid address hypothesis), and `calldatasize` (now reduced into UInt256 word semantics, so no extra size bound is needed) - Additional explicit precondition: the generic theorem surface now requires the observed transaction-context fields (`sender`, `thisAddress`, `msgValue`, `blockTimestamp`, `blockNumber`, `chainId`) to already fit the bounded source-side `Address`/`Uint256` domains - Outside the current generic theorem or current proof model: events/logs, proxy/delegatecall upgradeability, linked externals, local unsafe obligations, and other trust-surfaced features not captured by the current supported whole-contract fragment @@ -108,24 +108,28 @@ Key files: [`StatementEquivalence.lean`](../Compiler/Proofs/YulGeneration/Statem ### Phase 4: EVMYulLean Semantic Retargeting (safe-body EndToEnd target) -The retargeting module [`EvmYulLeanRetarget.lean`](../Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean) proves the following retargeting theorems: -- `backends_agree_on_bridged_builtins`: the `.verity` and `.evmYulLean` backends produce identical results at the `evalBuiltinCallWithBackendContext` level for all 36 bridged builtins (dispatch proof delegates to the 36 fully proven per-builtin context-lifted bridge lemmas in `EvmYulLeanBridgeLemmas.lean`) -- `evalYulExpr_evmYulLean_eq_on_bridged`: `evalYulExpr` agrees with the `.evmYulLean` backend-parameterized evaluator for every `BridgedExpr` expression, including nested calls to bridged builtins and backend-independent `tload`/`mload`; all builtin bridge dependencies are fully proven -- `execYulFuelWithBackend_verity_eq`: the backend-parameterized statement executor recovers existing `execYulFuel` semantics at `.verity`, giving the next induction a verified executor surface -- `execYulFuelWithBackend_eq_on_bridged_straight_stmts`: `.verity` and `.evmYulLean` statement execution agree for straight-line statement lists satisfying `BridgedStraightStmts`, covering value bindings, `letMany`'s shared revert behavior, and dedicated statement-call semantics for mapping-slot, literal-slot, and identifier-slot `sstore`, `mstore`, `tstore`, `stop`, `return`, and `revert`; all builtin bridge dependencies are fully proven -- `execYulFuelWithBackend_block_eq_on_bridged_straight_stmts`: `.block` wrappers around those straight-line lists preserve the same backend equivalence -- `execYulFuelWithBackend_if_eq_on_bridged_body`: `.if_` statements with bridged conditions and straight-line bodies preserve the same backend equivalence -- `execYulFuelWithBackend_switch_eq_on_bridged_cases`: `.switch` statements with bridged scrutinees and straight-line selected case/default bodies preserve the same backend equivalence -- `execYulFuelWithBackend_for_eq_on_bridged_parts`: `.for_` statements with straight-line init/body/post lists and a bridged condition preserve the same backend equivalence -- `execYulFuelWithBackend_eq_on_bridged_target`: recursive `.verity = .evmYulLean` backend equivalence for `BridgedTarget` executions whose nested statements satisfy `BridgedStmt` +The retargeting module [`EvmYulLeanRetarget.lean`](../Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean) proves the following retargeting facts. The backend-fuel executor facts are private transition evidence, not public proof authority: +- Private `backends_agree_on_bridged_builtins`: the `.verity` and `.evmYulLean` backends produce identical results at the `evalBuiltinCallWithBackendContext` level for all 36 bridged builtins (dispatch proof delegates to the 36 fully proven per-builtin context-lifted bridge lemmas in `EvmYulLeanBridgeLemmas.lean`) +- Private `evalYulExpr_evmYulLean_eq_on_bridged`: `evalYulExpr` agrees with the `.evmYulLean` backend-parameterized evaluator for every `BridgedExpr` expression, including nested calls to bridged builtins and backend-independent `tload`/`mload`; all builtin bridge dependencies are fully proven +- Private `execYulFuelWithBackend_verity_eq`: the backend-parameterized statement executor recovers existing `legacyExecYulFuel` semantics at `.verity`, giving the next induction a verified executor surface +- Private `execYulFuelWithBackend_eq_on_bridged_straight_stmts`: `.verity` and `.evmYulLean` statement execution agree for straight-line statement lists satisfying `BridgedStraightStmts`, covering value bindings, `letMany`'s shared revert behavior, and dedicated statement-call semantics for mapping-slot, literal-slot, and identifier-slot `sstore`, `mstore`, `tstore`, `stop`, `return`, and `revert`; all builtin bridge dependencies are fully proven +- Private `execYulFuelWithBackend_block_eq_on_bridged_straight_stmts`: `.block` wrappers around those straight-line lists preserve the same backend equivalence +- Private `execYulFuelWithBackend_if_eq_on_bridged_body`: `.if_` statements with bridged conditions and straight-line bodies preserve the same backend equivalence +- Private `execYulFuelWithBackend_switch_eq_on_bridged_cases`: `.switch` statements with bridged scrutinees and straight-line selected case/default bodies preserve the same backend equivalence +- Private `execYulFuelWithBackend_for_eq_on_bridged_parts`: `.for_` statements with straight-line init/body/post lists and a bridged condition preserve the same backend equivalence +- Private `execYulFuelWithBackend_eq_on_bridged_target`: recursive `.verity = .evmYulLean` backend equivalence for `BridgedTarget` executions whose nested statements satisfy `BridgedStmt` - `emitYul_runtimeCode_bridged`: the emitted runtime dispatch wrapper satisfies `BridgedTarget` when the IR function bodies, fallback/receive bodies, and internal helper statements it embeds satisfy `BridgedStmt` -- `emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies`: emitted runtime-code execution through Verity `execYulFuel` equals the EVMYulLean backend executor when those embedded function/entrypoint/internal bodies satisfy `BridgedStmts` -- `yulCodegen_preserves_semantics_evmYulLean`: the lower-level Layer-3 IR→Yul preservation theorem composed with the EVMYulLean backend runtime target; it intentionally remains parameterized by embedded-body `BridgedStmts` witnesses for callers that already have generated-Yul closure proofs -- `layers2_3_ir_matches_yul_evmYulLean`: the public safe-body EndToEnd composition over the EVMYulLean backend runtime target; raw external function-body `BridgedStmts` witnesses are discharged internally from `SupportedSpec`, static-parameter witnesses, and `BridgedSafeStmts` source-body witnesses, fallback/receive body witnesses are discharged from the public `none` hypotheses, and the internal-function-table witness is derived from `ContractWF` +- Private `emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies`: emitted runtime-code execution through Verity `legacyExecYulFuel` equals the EVMYulLean backend executor when those embedded function/entrypoint/internal bodies satisfy `BridgedStmts` +- The old transition-only `yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle` theorem has been removed. The retargeting module still keeps backend-wrapper equivalence facts as isolated transition evidence, but it no longer exports a Layer-3 preservation theorem that routes through the legacy reference oracle as public proof authority. +- `EndToEnd.lean` no longer defines `layers2_3_ir_matches_yul_evmYulLeanBackend` or other backend-wrapper transition lemmas. The retargeting evidence remains isolated in `EvmYulLeanRetarget.lean`, while public EndToEnd correctness targets native dispatcher execution through `interpretIRRuntimeNative`. - `genParamLoads_scalar_bridged`: scalar calldata parameter-loading prologues emitted by `genParamLoads` satisfy `BridgedStmts` - `genStaticTypeLoads_calldataload_bridged`: static scalar leaf-load helpers for fixed arrays/tuples satisfy `BridgedStmts` - `genParamLoads_static_scalar_bridged`: full calldata parameter-loading prologues for static scalar fixed arrays/tuples satisfy `BridgedStmts` -- `compileExpr_bridgedSource`: pure arithmetic/comparison/bit-operation source expressions in the `BridgedSourceExpr` fragment compile to `BridgedExpr` +- `compileExpr_bridgedSource`: arithmetic/comparison/bit-operation source expressions, parameter length identifiers, storage, storage-array length, and ADT tag/field reads whose compiler field lookup succeeds, singleton and nested mapping reads (`mapping`, `mappingWord`, `mappingUint`, `mapping2`, `mapping2Word`) through the abstract `mappingSlot` bridge, mapping struct-member reads (`structMember`, `structMember2`), the reserved exponentiation builtin surface, calldata/memory/transient reads, and syntactic `keccak256(offset, size)` source expressions in the `BridgedSourceExpr` fragment compile to `BridgedExpr`; `mappingSlot` remains the mapping-slot memory+keccak abstraction boundary, and `keccak256` remains outside the full source-vs-IR semantic core until memory-slice hashing is modeled by the source evaluator +- `compileExpr_keccak256_bridgedSource_of_exprCompileCore`: specialized native syntactic closure for `Expr.keccak256 offset size` when `offset` and `size` are compile-core expressions, without adding `keccak256` to the source semantic core +- `compileExpr_mappingChain_bridgedSource`: specialized native syntactic closure for `Expr.mappingChain field keys` when every key is in `BridgedSourceExpr`, through the abstract `mappingSlot` bridge +- `bridgedSafeStmts_letKeccak_of_exprCompileCore` / `bridgedSafeStmts_assignKeccak_of_exprCompileCore`: singleton `let`/`assign` bindings of syntactic `keccak256(offset, size)` are native safe bodies when `offset` and `size` are compile-core expressions +- `bridgedSafeStmts_externalMstoreLetKeccak_of_exprCompileCore`: external two-statement `mstore(...); let name := keccak256(...)` memory-preimage bodies are native safe bodies when all four subexpressions are compile-core - `compileStmtList_binding_leaf_bridged`: scalar-leaf `letVar`/`assignVar` source statement lists compile to `BridgedStmts` - `compileStmtList_pure_binding_bridged`: pure arithmetic/comparison/bit-operation `letVar`/`assignVar` source statement lists compile to `BridgedStmts` - `compileStmtList_storage_fragment_bridged`: pure binding plus unpacked single-slot `setStorage` source statement lists compile to `BridgedStmts` @@ -143,15 +147,15 @@ The retargeting module [`EvmYulLeanRetarget.lean`](../Compiler/Proofs/YulGenerat - `compileStmtList_internal_recursive_body_fragment_bridged`: mixed internal source-body fragments closed recursively under `Stmt.ite` compile to `BridgedStmts` - `compileStmtList_always_bridged`: universal aggregation theorem for `BridgedSafeStmts`; the external-call family (`internalCall`, `internalCallAssign`, `externalCallBind`, and `ecm`) remains outside the whitelist and behind explicit function-table hypotheses -The backend-parameterized executor now has a proved `.verity = .evmYulLean` theorem for recursive statement targets constrained by `BridgedTarget`, the generated runtime wrapper is proved to preserve that predicate and to execute equivalently under explicit body-closure hypotheses, Layer 3 now has a contract-level theorem whose Yul side is `interpretYulRuntimeWithBackend .evmYulLean`, and the public EndToEnd module exposes a safe-body wrapper over that target. Body closure now has a universal safe-body aggregation theorem for `BridgedSafeStmts`, and the public EndToEnd theorem uses that closure to discharge raw `BridgedStmts` body hypotheses for supported compiler-produced contracts while keeping the external-call/function-table family carved out where needed. +The backend-parameterized executor now has a proved `.verity = .evmYulLean` theorem for recursive statement targets constrained by `BridgedTarget`, and the generated runtime wrapper is proved to preserve that predicate and to execute equivalently under explicit body-closure hypotheses. Those backend-wrapper facts stay below EndToEnd in `EvmYulLeanRetarget.lean`. Body closure now has a universal safe-body aggregation theorem for `BridgedSafeStmts`, while the public EndToEnd theorem family targets native dispatcher execution through `interpretIRRuntimeNative` and keeps the external-call/function-table family carved out where needed. -Native-runtime transition status: the current theorem target is still the backend-parameterized Verity statement interpreter. The executable native EVMYulLean path lives in [`EvmYulLeanNativeHarness.lean`](../Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean), and the remaining theorem-transition plan is tracked in [`NATIVE_EVMYULLEAN_TRANSITION.md`](NATIVE_EVMYULLEAN_TRANSITION.md). +Native-runtime transition status: the public theorem target is native EVMYulLean dispatcher execution. The executable native EVMYulLean path lives in [`EvmYulLeanNativeHarness.lean`](../Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean), and the remaining theorem-transition plan is tracked in [`NATIVE_EVMYULLEAN_TRANSITION.md`](NATIVE_EVMYULLEAN_TRANSITION.md). The public native EndToEnd surface is the native result comparison/composition surface, the generated call-dispatcher and dispatcher-exec theorem family, and the concrete SimpleStorage theorem; the fuel-indexed `nativeIRRuntimeMatchesIR` seams and positive dispatcher-exec match family are file-local instead of public theorem authority. The no-mapping and mapping generated-dispatcher wrappers consume concrete dispatcher lowering and construct full emitted-runtime native lowering internally, while the call-dispatcher variants expose the actual generated `EvmYul.Yul.callDispatcher` premise and derive the dispatcher-exec projection internally. -Trust boundary (safe-body EndToEnd target): `BridgedExpr` expressions, `BridgedStraightStmts` statement lists, recursively nested `BridgedTarget` executions, source statement lists admitted by `BridgedSafeStmts`, emitted runtime wrappers whose embedded bodies are bridged, and public EndToEnd wrappers deriving those body bridges from source-level safe-body/static-param witnesses now inherit EVMYulLean builtin semantics with fully proven bridge dependencies. The stronger claim that native `EvmYul.Yul.callDispatcher` is the public semantic target remains pending until the native theorem path replaces `execYulFuelWithBackend`. +Trust boundary (public EndToEnd target): native `EvmYul.Yul.callDispatcher` execution is the public semantic target. The remaining backend-wrapper retargeting facts still mention private `execYulFuelWithBackend`/`interpretYulRuntimeWithBackend .evmYulLean` wrappers as lower-level transition evidence for the bridged safe-body fragment, but `EndToEnd.lean` does not export or privately compose compiler-correctness theorems over that target. Not yet proven in this module: - external-call/function-table body closure beyond the current `BridgedSafeStmts` whitelist -- native `EvmYul.Yul.callDispatcher` preservation for emitted runtime Yul +- full native `EvmYul.Yul.callDispatcher` preservation for emitted runtime Yul without the remaining concrete dispatcher-exec obligations Remaining gaps for whole-program retargeting: - 0 sorry-backed core equivalences diff --git a/scripts/check_native_transition_doc.py b/scripts/check_native_transition_doc.py index 954e78e55..c02118b80 100644 --- a/scripts/check_native_transition_doc.py +++ b/scripts/check_native_transition_doc.py @@ -9,11 +9,14 @@ from __future__ import annotations +import re import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] DOC = ROOT / "docs" / "NATIVE_EVMYULLEAN_TRANSITION.md" +DOD_DOC = ROOT / "docs" / "NATIVE_EVMYULLEAN_FULL_TRANSITION_DONE.md" +ROOT_COMPILER = ROOT / "Compiler.lean" END_TO_END = ROOT / "Compiler" / "Proofs" / "EndToEnd.lean" NATIVE_HARNESS = ( ROOT @@ -31,6 +34,56 @@ / "Backends" / "EvmYulLeanRetarget.lean" ) +BRIDGE_PREDICATES = ( + ROOT + / "Compiler" + / "Proofs" + / "YulGeneration" + / "Backends" + / "EvmYulLeanBridgePredicates.lean" +) +BRIDGE_LEMMAS = ( + ROOT + / "Compiler" + / "Proofs" + / "YulGeneration" + / "Backends" + / "EvmYulLeanBridgeLemmas.lean" +) +ADAPTER_CORRECTNESS = ( + ROOT + / "Compiler" + / "Proofs" + / "YulGeneration" + / "Backends" + / "EvmYulLeanAdapterCorrectness.lean" +) +BODY_CLOSURE = ( + ROOT + / "Compiler" + / "Proofs" + / "YulGeneration" + / "Backends" + / "EvmYulLeanBodyClosure.lean" +) +SOURCE_EXPR_CLOSURE = ( + ROOT + / "Compiler" + / "Proofs" + / "YulGeneration" + / "Backends" + / "EvmYulLeanSourceExprClosure.lean" +) +BUILTINS = ( + ROOT + / "Compiler" + / "Proofs" + / "YulGeneration" + / "ReferenceOracle" + / "Builtins.lean" +) +PRESERVATION = ROOT / "Compiler" / "Proofs" / "YulGeneration" / "Preservation.lean" +YULGEN_README = ROOT / "Compiler" / "Proofs" / "YulGeneration" / "README.md" NATIVE_ADAPTER = ( ROOT / "Compiler" @@ -47,6 +100,47 @@ / "Backends" / "EvmYulLeanNativeSmokeTest.lean" ) +RUNTIME_TYPES = ROOT / "Compiler" / "Proofs" / "YulGeneration" / "RuntimeTypes.lean" +LEGACY_PROOF_MODULES = ( + "Compiler.Proofs.YulGeneration.Codegen", + "Compiler.Proofs.YulGeneration.Equivalence", + "Compiler.Proofs.YulGeneration.StatementEquivalence", + "Compiler.Proofs.YulGeneration.Preservation", + "Compiler.Proofs.YulGeneration.Lemmas", +) +TRANSITION_ONLY_PUBLIC_FORBIDDEN_MODULES = LEGACY_PROOF_MODULES + ( + "Compiler.Proofs.YulGeneration.Backends.EvmYulLeanRetarget", + "Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeLemmas", +) +BRIDGE_LEMMAS_IMPORT_ALLOWLIST = ( + "PrintAxioms.lean", + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeTest.lean", + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean", +) +REFERENCE_ORACLE_IMPORT_ALLOWLIST = ( + "PrintAxioms.lean", + "Compiler/Proofs/YulGeneration/ReferenceOracle/Semantics.lean", + "Compiler/Proofs/YulGeneration/Codegen.lean", + "Compiler/Proofs/YulGeneration/Equivalence.lean", + "Compiler/Proofs/YulGeneration/Lemmas.lean", + "Compiler/Proofs/YulGeneration/Preservation.lean", + "Compiler/Proofs/YulGeneration/StatementEquivalence.lean", + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapterCorrectness.lean", + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean", + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeTest.lean", + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeDispatchOracleTest.lean", + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeSmokeTest.lean", + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean", + "Contracts/MacroTranslateInvariantTest.lean", + "Contracts/MacroTranslateRoundTripFuzz.lean", +) +LEGACY_PROOF_FILES = ( + ROOT / "Compiler" / "Proofs" / "YulGeneration" / "Codegen.lean", + ROOT / "Compiler" / "Proofs" / "YulGeneration" / "Equivalence.lean", + ROOT / "Compiler" / "Proofs" / "YulGeneration" / "StatementEquivalence.lean", + ROOT / "Compiler" / "Proofs" / "YulGeneration" / "Preservation.lean", + ROOT / "Compiler" / "Proofs" / "YulGeneration" / "Lemmas.lean", +) REQUIRED_SNIPPETS = ( "interpretYulRuntimeWithBackend .evmYulLean", @@ -57,17 +151,52 @@ "EvmYul.Yul.callDispatcher", "observable storage slot set explicitly", "only materializes pre-state storage for those slots", - "layers2_3_ir_matches_native_evmYulLean_of_interpreter_bridge", - "nativeIRRuntimeAgreesWithInterpreter", "nativeResultsMatchOn", - "nativeCallDispatcherAgreesWithInterpreter", - "layers2_3_ir_matches_native_evmYulLean_of_lowered_callDispatcher_bridge", + "nativeGeneratedCallDispatcherResultOf", + "nativeGeneratedCallDispatcherMatchesIROn", + "compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match", + "compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping", + "compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping", "explicitly observable final-storage slots", - "full-storage-projection", + "exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq", + "contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq", + "exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq", + "exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq", + "contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq", + "exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_projectResult_eq", + "exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_projectResult_eq", + "exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq", + "exec_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq", + "exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq", + "exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq", + "contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq", + "nativeDispatcherExecMatchesIRPositive_of_project_eq_match", + "lowerSwitchCasesNativeWithSwitchIds_find?_some_of_find_function", + "lowerSwitchCasesNativeWithSwitchIds_find?_none_of_find_function", + "buildSwitchSourceCases_eq_switchCases", + "lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_some_of_find_function", + "lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function", + "lowerStmtsNative_single_block_ok_singleton", + "lowerStmtsNative_block_stmts_eq", + "lowerStmtsNativeWithSwitchIds_let_head_eq", + "lowerStmtsNativeWithSwitchIds_if_head_eq", + "lowerStmtsNativeWithSwitchIds_singleton_switch_eq", + "lowerRuntimeContractNative_emitYul_noMapping_noInternals_noFallback_noReceive", + "lowerRuntimeContractNative_emitYul_mapping_noInternals_noFallback_noReceive_reserved", + "lowerStmtsNativeWithSwitchIds_revert_zero_zero", + "lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq", + "lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered", + "buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered", + "buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function", + "buildSwitch_noFallback_noReceive_lowered_inner_find?_none_of_find_function", "same explicit fuel", "default runtime fuel", - "native public theorem pending", + "retargeting evidence remains isolated", "not yet proved", + "`yulCodegen_preserves_semantics_evmYulLeanBackend`", + "`yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle`", + "`yulCodegen_preserves_semantics_via_reference_oracle`", + "not yet a native source-of-truth Layer 3 proof", "#1741", "#1738", "#1742", @@ -77,8 +206,99 @@ "`YulTransaction.chainId` must match", "EvmYul.chainId", "`chainid()` and `blobbasefee()` now fail closed on the selected native runtime path", + "`selfbalance` also fails closed on the selected native runtime path", "EvmYul.MIN_BASE_FEE_PER_BLOB_GAS", "`initialState_unbridgedEnvironmentDefaults`", + "remaining success-path blocker is the selected user-body result boundary", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel", + "generic native execution proof for", + "NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived", + "lowered selected `fn.body` at dispatcher fuel to `execIRFunction`", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel", + "`compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher`", + "discharges the lowered native runtime witness internally", + "public theorem no longer exposes full `DispatchGuardsSafe`", + "Legacy premise-taking `compile_preserves_native_evmYulLean_*`", + "wrappers are file-local", + "public `compile_preserves_native_evmYulLean_*` surface is limited", + "`SupportedSpec` carries the selected function calldata-threshold inventory", + "generatedFunctionCalldataThreshold_of_compile_ok_supported", + "transports that inventory across `compile`", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mapping", + "mapping-helper straight-body preservation path", + "NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_bridgedStraightStmts", + "no-mapping helper-free straight-body preservation bridge", + "NativeMappingFreeBridgedExpr", + "NativeMappingFreePreservableStraightStmt", + "NativeExprPreservesWord_lowerExprNative_of_mappingFreeBridgedExpr", + "NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_mappingFreePreservableStraightStmts", + "NativeMappingFreeSideConditionForBridgedStraightStmt", + "NativeMappingFreePreservableStraightStmts.of_bridgedStraightStmts", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mappingFree", + "`nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree`", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_closure_of_compile_ok_supported", + "selected native-body lowering success", + "without claiming native execution semantics", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_artifacts_of_compile_ok_supported", + "combines those lowered artifacts with the selected-body closure facts", + "selectedUserBodyClosureAndMatchedFresh_of_compile_ok_supported_switchFresh", + "recovers matched-flag freshness for the actual lowered user body", + "before the selected-body preservation callback loses the current", + "widen the preservation callback to carry", + "nativeGeneratedSelectorHitBodyPreservesMatched_mapping_of_switchFresh", + "NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh", + "mapping-specific straight-body side conditions private", + "smaller per-case lowering freshness premise", + "nativeGeneratedSwitchTempsFreshForNativeBodies_of_case_body_fresh", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree_caseFresh", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_caseFresh", + "remaining freshness work is to derive that per-case premise", + "singleton-`leave` base case", + "execIRStmts_single_leave_succ_succ", + "exec_block_leave_ok_add_ten", + "NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body", + "native `leave` exits through a revivable checkpoint", + "singleton-`stop` base case", + "execIRFunction_single_stop", + "exec_block_stop_halt_add_ten", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_stop_body", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_stop_body", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_stop_body", + "literal external returns", + "execIRFunction_mstore0_lit_return32", + "exec_lowerExprNative_mstore_lit_lit_ok_fuel", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_lit_return32", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_lit_return32", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_lit_return32", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_lit_return32", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_lit_return32", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_lit_return32", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_lit_return32", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_sload0_return32", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_sload0_return32", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_sload0_return32", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_sload0_return32", + "execIRFunction_oneParam_store0_value_stop", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_oneParam_store0_value_stop", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_oneParam_store0_value_stop", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_oneParam_store0_value_stop", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_oneParam_store0_value_stop", + "compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher_source_oneParam_store0_value_stop", + "Single-argument external returns", + "execIRFunction_mstore0_calldataload4_return32_of_args_cons", + "exec_lowerExprNative_mstore_lit_calldataload_lit_ok_fuel", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload4_return32", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload4_return32", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload4_return32", + "reusable aligned-calldata return seams", + "execIRFunction_mstore0_calldataload_aligned_return32", + "initialState_calldataload_aligned_arg_word", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload_aligned_return32", + "4 + 32 * idx < 2^64", + "remaining normal-return blocker is the generic body-shape discovery path", + "supply the mapping-free straight-body predicate automatically", ) FORBIDDEN_SNIPPETS = ( @@ -94,6 +314,57 @@ def normalize_ws(text: str) -> str: return " ".join(text.split()) +def contains_required_lean_decl(normalized_text: str, required: str) -> bool: + """Return whether a normalized Lean file contains the exact declaration.""" + + parts = required.split(maxsplit=1) + if len(parts) != 2 or parts[0] not in {"def", "theorem"}: + return required in normalized_text + keyword, name = parts + pattern = ( + r"(?:^| )(?:(?:private|protected)\s+)?" + + re.escape(keyword) + + r"\s+" + + re.escape(name) + + r"(?![A-Za-z0-9_'.])" + ) + return re.search(pattern, normalized_text) is not None + + +def theorem_signature(text: str, theorem_name: str) -> str: + """Return the theorem statement through its `:=` proof delimiter.""" + + match = re.search( + r"^\s*(?:private\s+)?theorem\s+" + re.escape(theorem_name) + r"\b", + text, + re.MULTILINE, + ) + if match is None: + return "" + proof_start = text.find(":=", match.start()) + if proof_start < 0: + return text[match.start() :] + return text[match.start() : proof_start] + + +def public_theorem_signatures(text: str) -> list[tuple[str, str]]: + """Return public theorem names with their statement through the proof delimiter.""" + + signatures: list[tuple[str, str]] = [] + pattern = re.compile( + r"(?m)^[ \t]*(?!private\b)(?!protected\b)theorem\s+" + r"(?P[A-Za-z0-9_'.]+)\b" + ) + for match in pattern.finditer(text): + proof_start = text.find(":=", match.start()) + if proof_start < 0: + signature = text[match.start() :] + else: + signature = text[match.start() : proof_start] + signatures.append((match.group("name"), signature)) + return signatures + + def check_doc(text: str) -> list[str]: normalized = normalize_ws(text) errors: list[str] = [] @@ -123,15 +394,46 @@ def check_doc(text: str) -> list[str]: return errors +def check_definition_of_done_doc(text: str) -> list[str]: + """Keep the definition-of-done baseline synchronized with current names.""" + + normalized = normalize_ws(text) + errors: list[str] = [] + + for required in ( + "interpretYulRuntimeWithBackend .evmYulLean", + "yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle", + "Native.interpretIRRuntimeNative", + "EvmYul.Yul.callDispatcher", + ): + if normalize_ws(required) not in normalized: + errors.append( + f"{DOD_DOC.relative_to(ROOT)} is missing current native-transition " + f"definition-of-done text: `{required}`" + ) + + for forbidden in ( + "interpretYulRuntimeEvmYulLeanFuelWrapperDefaultFuel", + "interpretYulRuntimeEvmYulLeanFuelWrapper", + "evmYulLeanFuelWrapperDefaultFuel", + ): + if forbidden in normalized: + errors.append( + f"{DOD_DOC.relative_to(ROOT)} must not mention removed " + f"EVMYulLean fuel-wrapper surface `{forbidden}`" + ) + + return errors + + def check_public_theorem_target( end_to_end_text: str, native_harness_text: str, retarget_text: str ) -> list[str]: - """Pin the current transition boundary until the native theorem flips. + """Pin the current transition boundary after EndToEnd wrapper removal. - This guard should be updated in the same PR that proves the native - preservation theorem and retargets the public EndToEnd path. Until then, - the public theorem must still visibly target the backend-parameterized - interpreter, while the native harness remains an executable side path. + Public EndToEnd correctness targets native dispatcher execution. The old + backend-parameterized interpreter lemmas remain isolated in the lower + retargeting module while generated native direct-match coverage is widened. """ errors: list[str] = [] @@ -139,43 +441,1075 @@ def check_public_theorem_target( normalized_native_harness = normalize_ws(native_harness_text) normalized_retarget = normalize_ws(retarget_text) - if "interpretYulRuntimeWithBackend .evmYulLean" not in normalized_end_to_end: + if "interpretYulRuntimeWithBackend .evmYulLean" in normalized_end_to_end: errors.append( - "Compiler/Proofs/EndToEnd.lean must still expose the current " - "`interpretYulRuntimeWithBackend .evmYulLean` public theorem target " - "until the native preservation theorem is proved and this guard is updated" + "Compiler/Proofs/EndToEnd.lean must not mention the legacy " + "`interpretYulRuntimeWithBackend .evmYulLean` transition target; " + "keep that evidence isolated in EvmYulLeanRetarget.lean" ) - for required_native_seam in ( + if "evalBuiltinCall" in end_to_end_text: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not directly mention legacy " + "builtin-dispatch wrapper `evalBuiltinCall`; keep those notes and " + "dependencies below the public EndToEnd surface" + ) + + for theorem_name, signature in public_theorem_signatures(end_to_end_text): + for forbidden_lowering_obligation in ( + "hLowerRuntime", + "hLowerDispatcher", + "hLower", + ): + if re.search(r"\b" + re.escape(forbidden_lowering_obligation) + r"\b", signature): + errors.append( + "Compiler/Proofs/EndToEnd.lean public theorem " + f"`{theorem_name}` must not expose native lowering witness " + f"obligation `{forbidden_lowering_obligation}`" + ) + + for required_native_surface in ( "def nativeResultsMatch", - "def yulResultsAgreeOn", "def nativeResultsMatchOn", - "def nativeIRRuntimeAgreesWithInterpreter", - "def nativeCallDispatcherAgreesWithInterpreter", - "theorem nativeIRRuntimeAgreesWithInterpreter_of_lowered_callDispatcher_agree", - "interpretYulRuntimeWithBackendFuel .evmYulLean fuel", - "hFuel : fuel = sizeOf (Compiler.emitYul contract).runtimeCode + 1", - "theorem layer3_contract_preserves_semantics_native_of_interpreter_bridge", - "theorem layer3_contract_preserves_semantics_native_of_lowered_callDispatcher_bridge", - "theorem layers2_3_ir_matches_native_evmYulLean_of_interpreter_bridge", - "theorem layers2_3_ir_matches_native_evmYulLean_of_lowered_callDispatcher_bridge", - ): - if required_native_seam not in normalized_end_to_end: + "theorem validateNativeRuntimeEnvironment_ofIR_representableEnvironment", + "theorem validateNativeRuntimeEnvironment_ofIR_globalDefaults", + "def nativeMappingSlotFunctionDefinition", + "theorem lowerFunctionDefinitionNativeWithReserved_mappingSlotFuncAt_zero", + "theorem lowerFunctionDefinitionNativeWithReserved_mappingSlotFuncAt_zero_body", + "theorem lowerRuntimeContractNative_emitYul_mapping_noInternals_noFallback_noReceive_reserved", + "theorem lowerRuntimeContractNative_emitYul_mapping_ok_dispatcher_reserved", + ): + if not contains_required_lean_decl(normalized_native_harness, required_native_surface): + errors.append( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean " + "must own the native theorem/result surface " + f"`{required_native_surface}` until the generated-fragment " + "native bridge is discharged" + ) + + for required_end_to_end_native_surface in ( + "def nativeIRRuntimeMatchesIR", + "def nativeDispatcherExecMatchesIRPositive", + "theorem nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_positive_match", + "theorem nativeDispatcherExecMatchesIRPositive_of_project_eq_match", + "theorem nativeIRRuntimeMatchesIR_of_generated_lowered_dispatcherExec_project_eq_match", + "theorem nativeDispatcherExecMatchesIRPositive_of_exec_yulHalt_project_eq_match", + "theorem nativeDispatcherExecMatchesIRPositive_of_exec_error_project_eq_match", + ): + if not contains_required_lean_decl( + normalized_end_to_end, required_end_to_end_native_surface + ): + errors.append( + "Compiler/Proofs/EndToEnd.lean must own the native-vs-IR " + "comparison surface " + f"`{required_end_to_end_native_surface}` after the native " + "harness was split away from the full IR interpreter" + ) + + for required_native_seam in ( + "def nativeGeneratedCallDispatcherResultOf", + "def nativeGeneratedCallDispatcherMatchesIROn", + "theorem compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match", + "theorem compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping", + "theorem compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_match", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure_ofIR_environment", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_positive_body_closure_ofIR_globalDefaults", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_eq_match", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_environment", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_dispatcherExec_project_body_closure_ofIR_globalDefaults", + "theorem generatedRuntimeNativeFragment_of_compile_ok_supported_safe", + "theorem validateGeneratedRuntimeNativeFragment_of_compile_ok_supported_safe", + "theorem generatedRuntimeSelectedFunctionBodyBridged_of_compile_ok_supported", + "theorem lowerStmtsNativeWithSwitchIds_selectedFunctionBody_exists_of_compile_ok_supported", + "theorem selectedFunctionBodyBridgedAndLowered_of_compile_ok_supported", + "theorem nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_exists_of_compile_ok_supported", + "theorem lowerRuntimeContractNative_of_compile_ok_supported_exists", + "theorem lowerRuntimeContractNative_of_compile_ok_supported_noMapping", + "theorem lowerRuntimeContractNative_of_compile_ok_supported_noMapping_ok_dispatcher", + "theorem lowerRuntimeContractNative_of_compile_ok_supported_mapping_reserved", + "theorem lowerRuntimeContractNative_of_compile_ok_supported_mapping_ok_dispatcher_reserved", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved", + "theorem nativeIRRuntimeMatchesIR_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved", + "theorem layer3_contract_preserves_semantics_native_of_generated_dispatcherExec_positive_match", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_positive_external_bodies_match", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_positive_body_closure", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_external_bodies_match", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherExec_project_body_closure", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved", + "theorem layer3_contract_preserves_semantics_native_of_compiled_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_external_bodies_match", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_match", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure_ofIR_environment", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive_body_closure_ofIR_globalDefaults", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_external_bodies_match", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_match", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_environment", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_project_body_closure_ofIR_globalDefaults", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_environment", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping_ofIR_environment", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_noMapping_ofIR_globalDefaults", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping_ofIR_environment", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_noMapping_ofIR_globalDefaults", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_environment", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_positive_body_closure_mapping_reserved_ofIR_globalDefaults", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_environment", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_lowered_runtime_dispatcherStmts_project_body_closure_mapping_reserved_ofIR_globalDefaults", + "theorem simpleStorageNativeCallDispatcherMatchBridge_of_per_case", + "theorem simpleStorageNativeRetrieveHitMatchBridge_proved", + "theorem simpleStorageNativeStoreHitMatchBridge_proved", + "theorem simpleStorageNativeSelectorMissMatchBridge_proved", + "theorem nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_exists_of_compile_ok_supported", + "theorem nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_exists_of_compile_ok_supported", + "theorem nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_exists_of_compile_ok_supported", + "theorem nativeGeneratedCallDispatcherResult_selector_hit_error_matchesIR_exists_of_compile_ok_supported", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported", + "theorem compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher", + "theorem DispatchGuardsSafe.of_value_safe_of_threshold", + "theorem compiledFunctionCalldataThreshold_of_forall₂", + "theorem generatedFunctionCalldataThreshold_of_compile_ok_supported", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_store0_calldataload4_stop", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_sload0_return32", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_stop_body", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_stop_body", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_stop_body", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_lit_return32", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_lit_return32", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_lit_return32", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_lit_return32", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_lit_return32", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_lit_return32", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_lit_return32", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_sload0_return32", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_sload0_return32", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_sload0_return32", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_sload0_return32", + "theorem execIRFunction_oneParam_store0_value_stop", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_oneParam_store0_value_stop", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_oneParam_store0_value_stop", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_oneParam_store0_value_stop", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_oneParam_store0_value_stop", + "theorem compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher_source_oneParam_store0_value_stop", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload4_return32", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload4_return32", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload4_return32", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload_aligned_return32", + "def NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived", + "def NativeGeneratedSelectedUserBodyResultBridgeAtFuel", + "def NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived", + "def NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel", + "def NativeGeneratedSelectorHitUserBodyGeneratedPrefixContinuation", + "theorem NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_preserves", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_nativeStmtsWriteNames_not_mem", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mapping", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_mappingFreePreservableStraightStmts", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mappingFree", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_empty_body", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_closure_of_compile_ok_supported", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.selected_body_artifacts_of_compile_ok_supported", + "theorem selectedUserBodyClosureAndMatchedFresh_of_compile_ok_supported_switchFresh", + "theorem nativeGeneratedSelectorHitBodyPreservesMatched_mapping_of_switchFresh", + "theorem NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh", + "theorem nativeGeneratedSwitchTempsFreshForNativeBodies_of_case_body_fresh", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree_caseFresh", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_caseFresh", + "theorem NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_exec_bridge", + "theorem NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_selected_user_body_exec_only", + "theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_exec_bridge", + "theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_forall_stmt_write_not_mem", + "theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_nativeStmtsWriteNames_not_mem", + "theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_mappingFreePreservableStraightStmts", + "theorem NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_and_preserves", + "theorem NativeGeneratedSelectorHitBridge.of_success_predicate_and_generated_guard_reverts_threshold", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_success_bridge_threshold", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree", + "theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result_threshold", + ): + if not contains_required_lean_decl(normalized_end_to_end, required_native_seam): errors.append( "Compiler/Proofs/EndToEnd.lean must keep the native theorem seam " f"`{required_native_seam}` explicit until the generated-fragment " "native bridge is discharged" ) + unsafe_leave_preservation_patterns = ( + r"(?m)^[ \t]*(?:private\s+)?theorem\s+NativeStmtPreservesWord_leave\b", + r"(?m)^[ \t]*(?:private\s+)?theorem\s+NativeBlockPreservesWord_leave\b", + r"(?m)^[ \t]*(?:private\s+)?theorem\s+NativeBlockPreservesWord_single_leave\b", + ) + for pattern in unsafe_leave_preservation_patterns: + if re.search(pattern, native_harness_text) or re.search(pattern, end_to_end_text): + errors.append( + "The native transition must not close the selected-body result " + "bridge by asserting matched-flag preservation for raw `leave`: " + "`leave` exits through a revivable checkpoint, so preserve the " + "exec-only bridge until a checkpoint-aware dispatcher invariant " + "is proved." + ) + + private_selected_hit_seams = ( + ("def", "NativeGeneratedSelectorHitBridge"), + ("def", "NativeGeneratedSelectorHitBodyBridge"), + ("def", "NativeGeneratedSelectorHitUserBodyBridge"), + ("def", "NativeGeneratedSelectorHitUserBodyBridgeAtFuel"), + ("def", "NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored"), + ("def", "NativeGeneratedSelectorHitUserBodyBridgeAtFuelRevived"), + ("def", "NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived"), + ("def", "NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived"), + ("def", "NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived"), + ("def", "NativeGeneratedSelectedUserBodyResultBridgeAtFuel"), + ("def", "NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel"), + ("def", "NativeGeneratedSelectorHitArtifactBridge"), + ("def", "NativeGeneratedSelectorHitDispatcherContinuation"), + ("def", "NativeGeneratedSelectorHitUserBodyGeneratedPrefixContinuation"), + ("theorem", "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_halt"), + ( + "theorem", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_preserves", + ), + ( + "theorem", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_nativeStmtsWriteNames_not_mem", + ), + ( + "theorem", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mapping", + ), + ( + "theorem", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mappingFree", + ), + ( + "theorem", + "nativeGeneratedSelectorHitBodyPreservesMatched_mapping_of_switchFresh", + ), + ( + "theorem", + "NativeGeneratedSelectorHitSuccessBridge.of_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_switchFresh", + ), + ( + "theorem", + "nativeGeneratedSwitchTempsFreshForNativeBodies_of_case_body_fresh", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree_caseFresh", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mapping_caseFresh", + ), + ( + "theorem", + "NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body", + ), + ("theorem", "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_stop_body"), + ("theorem", "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_stop_body"), + ("theorem", "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_lit_return32"), + ("theorem", "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_lit_return32"), + ("theorem", "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_lit_return32"), + ("theorem", "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_lit_return32"), + ("theorem", "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_sload0_return32"), + ("theorem", "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_sload0_return32"), + ("theorem", "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_oneParam_store0_value_stop"), + ("theorem", "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_oneParam_store0_value_stop"), + ("theorem", "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload4_return32"), + ("theorem", "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload4_return32"), + ("theorem", "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_empty_body"), + ("theorem", "NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_exec_bridge"), + ( + "theorem", + "NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_selected_user_body_exec_only", + ), + ("theorem", "NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_exec_bridge"), + ( + "theorem", + "NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_forall_stmt_write_not_mem", + ), + ( + "theorem", + "NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_nativeStmtsWriteNames_not_mem", + ), + ( + "theorem", + "NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_and_preserves", + ), + ( + "theorem", + "NativeGeneratedSelectorHitUserBodyBridgeAtFuelRevived.of_execIRFunction", + ), + ("theorem", "NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_revived"), + ( + "theorem", + "NativeGeneratedSelectorHitUserBodyBridgeAtFuelRestored.of_execIRFunction", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_stop_body", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_lit_return32", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_lit_return32", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_lit_return32", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_sload0_return32", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_sload0_return32", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_oneParam_store0_value_stop", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_oneParam_store0_value_stop", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload4_return32", + ), + ( + "theorem", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload_aligned_return32", + ), + ( + "theorem", + "NativeGeneratedSelectorHitArtifactBridge.of_body_bridge_and_continuation", + ), + ( + "theorem", + "NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_and_continuation", + ), + ( + "theorem", + "NativeGeneratedSelectorHitArtifactBridge.of_user_body_bridge_atFuel_and_continuation", + ), + ("theorem", "NativeGeneratedSelectorHitBridge.of_artifact_bridge"), + ( + "theorem", + "NativeGeneratedSelectorHitBridge.of_success_bridge_and_generated_guard_reverts", + ), + ( + "theorem", + "NativeGeneratedSelectorHitBridge.of_success_predicate_and_generated_guard_reverts", + ), + ( + "theorem", + "NativeGeneratedSelectorHitBridge.of_success_predicate_and_generated_guard_reverts_threshold", + ), + ( + "theorem", + "NativeGeneratedSelectorHitSuccessBridge.of_user_body_exec_bridge_atFuel_revived_and_continuation", + ), + ) + for kind, name in private_selected_hit_seams: + private_decl = f"private {kind} {name}" + if private_decl not in normalized_end_to_end: + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep the selected " + "selector-hit bridge seam private: " + f"`{private_decl}`" + ) + public_decl_pattern = re.compile( + rf"(?m)^[ \t]*(?!private\b){kind}\s+{re.escape(name)}\b" + ) + if public_decl_pattern.search(end_to_end_text): + errors.append( + "Compiler/Proofs/EndToEnd.lean must not expose the selected " + "selector-hit bridge seam publicly: " + f"`{kind} {name}`" + ) + + exact_generated_theorem = "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported" + source_generated_theorem = ( + "compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher" + ) + public_halt_bridge_pattern = re.compile( + r"(?m)^[ \t]*def\s+NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel\b" + ) + private_halt_bridge_pattern = re.compile( + r"(?m)^[ \t]*private\s+def\s+NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel\b" + ) + public_success_bridge_pattern = re.compile( + r"(?m)^[ \t]*def\s+NativeGeneratedSelectorHitSuccessBridge\b" + ) + private_success_bridge_pattern = re.compile( + r"(?m)^[ \t]*private\s+def\s+NativeGeneratedSelectorHitSuccessBridge\b" + ) + if public_halt_bridge_pattern.search(end_to_end_text) is None: + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep the public exact " + "generated callDispatcher selected user-body halt bridge publicly nameable: " + "`def NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel`" + ) + if private_halt_bridge_pattern.search(end_to_end_text): + errors.append( + "Compiler/Proofs/EndToEnd.lean must not make the public exact " + "generated callDispatcher selected user-body halt bridge private while the public " + "theorem exposes it: " + "`NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel`" + ) + if public_success_bridge_pattern.search(end_to_end_text) is None: + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep the remaining " + "success-case selector-hit bridge publicly nameable: " + "`def NativeGeneratedSelectorHitSuccessBridge`" + ) + if private_success_bridge_pattern.search(end_to_end_text): + errors.append( + "Compiler/Proofs/EndToEnd.lean must not make the remaining " + "success-case selector-hit bridge private while private adapters " + "still close over it: " + "`NativeGeneratedSelectorHitSuccessBridge`" + ) + + exact_generated_signature = theorem_signature(end_to_end_text, exact_generated_theorem) + if not exact_generated_signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep the public exact generated " + f"callDispatcher theorem `{exact_generated_theorem}` explicit" + ) + else: + for required_exact_signature_target in ( + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel", + "nativeGeneratedCallDispatcherResultOf", + ): + if required_exact_signature_target not in exact_generated_signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean public exact generated " + f"callDispatcher theorem `{exact_generated_theorem}` must " + f"expose `{required_exact_signature_target}` in its signature" + ) + for forbidden_exact_signature_target in ( + "NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived", + "NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel", + "NativeGeneratedSelectorHitUserBodyGeneratedPrefixContinuation", + "DispatchGuardsSafe", + "selectorDispatchedFunctions spec", + "lowerRuntimeContractNative", + ): + if forbidden_exact_signature_target in exact_generated_signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean public exact generated " + f"callDispatcher theorem `{exact_generated_theorem}` must " + "hide the selected user-body adapter or full guard detail " + f"`{forbidden_exact_signature_target}` behind " + "`NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel`" + ) + if "interpretIRRuntimeNative" in exact_generated_signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean public exact generated " + f"callDispatcher theorem `{exact_generated_theorem}` must not " + "expose `interpretIRRuntimeNative` as its public result target" + ) + + source_generated_signature = theorem_signature(end_to_end_text, source_generated_theorem) + if not source_generated_signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep the public source-level " + f"generated callDispatcher theorem `{source_generated_theorem}` explicit" + ) + else: + for required_source_signature_target in ( + "sourceResultMatchesNativeOn", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel", + "interpretIRRuntimeNative", + ): + if required_source_signature_target not in source_generated_signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean public source-level generated " + f"callDispatcher theorem `{source_generated_theorem}` must " + f"expose `{required_source_signature_target}` in its signature" + ) + for forbidden_source_signature_target in ( + "DispatchGuardsSafe", + "NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived", + "lowerRuntimeContractNative", + "nativeGeneratedCallDispatcherResultOf", + ): + if forbidden_source_signature_target in source_generated_signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean public source-level generated " + f"callDispatcher theorem `{source_generated_theorem}` must " + "hide the selected user-body adapter or older runtime target " + f"`{forbidden_source_signature_target}`" + ) + + allowed_public_compile_preserves = { + source_generated_theorem, + } + public_compile_preserves_pattern = re.compile( + r"(?m)^[ \t]*(?!private\b)theorem\s+" + r"(compile_preserves_native_evmYulLean_[A-Za-z0-9_']+)\b" + ) + for public_match in public_compile_preserves_pattern.finditer(end_to_end_text): + public_name = public_match.group(1) + if public_name not in allowed_public_compile_preserves: + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep legacy " + "`compile_preserves_native_evmYulLean_*` wrappers private; " + f"unexpected public theorem `{public_name}`" + ) + + deprecated_exact_wrappers = ( + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_success_only_atFuel_revived_and_continuation", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_body_halt_bridge_atFuel", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_body_bridge_and_continuation", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_and_continuation", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_and_continuation", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_restored_and_continuation", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_bridge_atFuel_revived_and_continuation", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_atFuel_revived_and_continuation", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_success_only_atFuel_revived", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_empty_selected_body", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_preserves", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_result", + ) + deprecated_exact_pattern = re.compile( + r"attribute\s+\[deprecated\s+" + + re.escape(exact_generated_theorem) + + r"\s+\(since\s*:=\s*\"2026-05-07\"\)\]\s+" + + r"(?P(?:\s*(?:" + + "|".join( + re.escape(wrapper) + for wrapper in sorted(deprecated_exact_wrappers, key=len, reverse=True) + ) + + r"))+)", + re.MULTILINE, + ) + deprecated_exact_match = deprecated_exact_pattern.search(end_to_end_text) + if deprecated_exact_match is None: + errors.append( + "Compiler/Proofs/EndToEnd.lean exact generated callDispatcher " + "compatibility wrappers must be deprecated in favor of " + f"`{exact_generated_theorem}`" + ) + else: + wrapper_block = deprecated_exact_match.group("wrapper_block") + for wrapper in deprecated_exact_wrappers: + if wrapper not in wrapper_block: + errors.append( + "Compiler/Proofs/EndToEnd.lean exact generated " + f"callDispatcher compatibility wrapper `{wrapper}` must " + f"be included in the deprecation block for `{exact_generated_theorem}`" + ) + + deprecated_interpret_wrappers = ( + "compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match", + "compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_environment", + "compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_ofIR_globalDefaults", + "compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_environment", + "compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_noMapping_dispatcher_ofIR_globalDefaults", + "compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_environment", + "compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_globalDefaults", + ) + deprecated_interpret_pattern = re.compile( + r"attribute\s+\[deprecated\s+" + r"compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match" + r"\s+\(since\s*:=\s*\"2026-05-07\"\)\]\s+" + + r"(?P(?:\s*(?:" + + "|".join( + re.escape(wrapper) + for wrapper in sorted(deprecated_interpret_wrappers, key=len, reverse=True) + ) + + r"))+)", + re.MULTILINE, + ) + deprecated_interpret_match = deprecated_interpret_pattern.search(end_to_end_text) + if deprecated_interpret_match is None: + errors.append( + "Compiler/Proofs/EndToEnd.lean interpretIRRuntimeNative " + "compatibility wrappers must be deprecated in favor of " + "`compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match`" + ) + else: + wrapper_block = deprecated_interpret_match.group("wrapper_block") + for wrapper in deprecated_interpret_wrappers: + if wrapper not in wrapper_block: + errors.append( + "Compiler/Proofs/EndToEnd.lean interpretIRRuntimeNative " + f"compatibility wrapper `{wrapper}` must be included in " + "the deprecation block for " + "`compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match`" + ) + + deprecated_interpret_eq_wrappers = ( + "nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported", + "nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported_except_mapping_writes_stmt_safety", + ) + deprecated_interpret_eq_pattern = re.compile( + r"attribute\s+\[deprecated\s+nativeGeneratedCallDispatcherResultOf" + r"\s+\(since\s*:=\s*\"2026-05-07\"\)\]\s+" + + r"(?P(?:\s*(?:" + + "|".join( + re.escape(wrapper) + for wrapper in sorted(deprecated_interpret_eq_wrappers, key=len, reverse=True) + ) + + r"))+)", + re.MULTILINE, + ) + deprecated_interpret_eq_match = deprecated_interpret_eq_pattern.search(end_to_end_text) + if deprecated_interpret_eq_match is None: + errors.append( + "Compiler/Proofs/EndToEnd.lean interpretIRRuntimeNative equality " + "wrappers must be deprecated in favor of " + "`nativeGeneratedCallDispatcherResultOf`" + ) + else: + wrapper_block = deprecated_interpret_eq_match.group("wrapper_block") + for wrapper in deprecated_interpret_eq_wrappers: + if wrapper not in wrapper_block: + errors.append( + "Compiler/Proofs/EndToEnd.lean interpretIRRuntimeNative " + f"equality wrapper `{wrapper}` must be included in the " + "deprecation block for `nativeGeneratedCallDispatcherResultOf`" + ) + + for public_call_dispatcher_theorem in ( + "compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match", + "compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping", + "compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping", + ): + signature = theorem_signature(end_to_end_text, public_call_dispatcher_theorem) + if "nativeGeneratedCallDispatcherResultOf" not in signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean public generated " + f"`{public_call_dispatcher_theorem}` theorem must conclude " + "the direct projected `EvmYul.Yul.callDispatcher` result via " + "`nativeGeneratedCallDispatcherResultOf`, not the thin runtime adapter" + ) + if "interpretIRRuntimeNative" in signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean public generated " + f"`{public_call_dispatcher_theorem}` theorem must not expose " + "`interpretIRRuntimeNative` as its public result target" + ) + deprecated_pattern = re.compile( + r"@\[deprecated\s+" + r"compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match" + r"\s+\(since\s*:=\s*\"2026-05-07\"\)\]\s*" + r"(?:private\s+)?theorem\s+" + re.escape(public_call_dispatcher_theorem) + r"\b", + re.MULTILINE, + ) + if not deprecated_pattern.search(end_to_end_text): + errors.append( + "Compiler/Proofs/EndToEnd.lean generated callDispatcher " + f"compatibility wrapper `{public_call_dispatcher_theorem}` " + "must be marked deprecated in favor of " + "`compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match`" + ) + + if re.search( + r"^\s*theorem\s+compile_preserves_native_evmYulLean_of_nativeResultsMatchOn\b", + end_to_end_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep the generic " + "`compile_preserves_native_evmYulLean_of_nativeResultsMatchOn` " + "adapter theorem file-local; public compiler correctness should " + "target explicit native result values" + ) + + for dispatcher_exec_public_seam in ( + "def nativeGeneratedDispatcherExecMatchesIROn", + "theorem compile_preserves_native_evmYulLean_of_generated_dispatcherExec_match", + "theorem compile_preserves_native_evmYulLean_of_lowered_generated_dispatcher_noMapping", + "theorem compile_preserves_native_evmYulLean_of_lowered_generated_dispatcher_mapping", + ): + if re.search( + r"^\s*" + re.escape(dispatcher_exec_public_seam) + r"\b", + end_to_end_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep dispatcher-exec " + "compatibility seams private; public generated correctness " + "must expose `EvmYul.Yul.callDispatcher` rather than " + f"`{dispatcher_exec_public_seam}`" + ) + + for removed_transition_seam in ( + "layer3_contract_preserves_semantics_evmYulLeanBackend_with_function_bridge", + "layer3_contract_preserves_semantics_evmYulLeanBackend", + "layer3_contract_preserves_semantics_native_of_evmYulLean_bridge", + "layers2_3_ir_matches_yul_evmYulLeanBackend_with_function_bridge", + "layers2_3_ir_matches_yul_evmYulLeanBackend", + "layers2_3_ir_matches_native_evmYulLean_of_evmYulLean_bridge", + "compile_preserves_native_evmYulLean_of_generated_dispatcherExec_match", + "compile_preserves_native_evmYulLean_of_generated_callDispatcher_match", + "compile_preserves_native_evmYulLean_of_lowered_generated_dispatcher_noMapping", + "compile_preserves_native_evmYulLean_of_lowered_generated_dispatcher_mapping", + "simpleStorage_endToEnd_evmYulLeanBackend", + ): + if re.search( + r"^\s*(?:private\s+)?theorem\s+" + + re.escape(removed_transition_seam) + + r"\b", + end_to_end_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/EndToEnd.lean must not define removed " + f"backend-wrapper transition lemma `{removed_transition_seam}`" + ) + + for private_native_identity_seam in ( + "layer3_contract_preserves_semantics_native", + "layers2_3_ir_matches_native_evmYulLean", + ): + if re.search( + r"^\s*theorem\s+" + + re.escape(private_native_identity_seam) + + r"\b", + end_to_end_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/EndToEnd.lean must not export arbitrary-fuel " + f"native identity seam `{private_native_identity_seam}`; keep " + "the public surface on generated-dispatcher native wrappers" + ) + + for removed_fuel_wrapper_seam in ( + "def yulResultsAgreeOn", + "def nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper", + "def nativeCallDispatcherAgreesWithEvmYulLeanFuelWrapper", + "def nativeDispatcherBlockAgreesWithEvmYulLeanFuelWrapper", + "def nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapper", + "def nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapperPositive", + "theorem nativeResultsMatchOn_ok_of_resultsMatch_of_yulResultsAgreeOn", + "theorem yulResultsAgreeOn_of_resultsMatch_of_nativeResultsMatchOn", + "theorem nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper_of_ok_agree", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapperPositive_of_exec_ok_agree", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapperPositive_of_exec_yulHalt_agree", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapperPositive_of_exec_yulHalt_project_eq_agree", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapperPositive_of_exec_error_agree", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapperPositive_of_exec_error_project_eq_agree", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapper_of_positive", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapper_of_exec_ok_agree", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapper_of_exec_yulHalt_agree", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapper_of_exec_error_agree", + "theorem nativeDispatcherBlockAgreesWithEvmYulLeanFuelWrapper_of_exec_agree", + "theorem nativeCallDispatcherAgreesWithEvmYulLeanFuelWrapper_of_dispatcherBlock_agree", + "theorem nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper_of_lowered_callDispatcher_agree", + "theorem nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper_of_lowered_dispatcherExec_positive_agree", + "theorem nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper_of_generated_lowered_callDispatcher_agree", + "theorem nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper_of_generated_lowered_dispatcherExec_positive_agree", + ): + if removed_fuel_wrapper_seam in normalized_end_to_end: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not reintroduce the removed " + "native fuel-wrapper agreement seam " + f"`{removed_fuel_wrapper_seam.removeprefix('theorem ').removeprefix('def ')}`" + ) + + for forbidden_ir_runtime_alias in ( + "def nativeIRRuntimeAgreesWithEvmYulLean ", + "theorem nativeIRRuntimeAgreesWithEvmYulLean_of_ok_agree ", + "theorem nativeIRRuntimeAgreesWithEvmYulLean_of_nativeIRRuntimeMatchesIR ", + "theorem nativeIRRuntimeAgreesWithEvmYulLean_of_ok_nativeResultsMatchOn ", + "theorem nativeIRRuntimeAgreesWithEvmYulLean_of_lowered_callDispatcher_agree ", + "theorem nativeIRRuntimeAgreesWithEvmYulLean_of_lowered_dispatcherExec_positive_agree ", + "theorem nativeIRRuntimeAgreesWithEvmYulLean_of_generated_lowered_callDispatcher_agree ", + "theorem nativeIRRuntimeAgreesWithEvmYulLean_of_generated_lowered_dispatcherExec_positive_agree ", + "theorem nativeIRRuntimeAgreesWithEvmYulLean_of_compiled_generated_lowered_dispatcherExec_positive_agree ", + "theorem nativeIRRuntimeAgreesWithEvmYulLean_of_compiled_generated_lowered_dispatcherExec_positive_body_closure ", + ): + if forbidden_ir_runtime_alias in normalized_end_to_end: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not reintroduce the hidden " + "native IR-runtime fuel-wrapper alias " + f"`{forbidden_ir_runtime_alias.strip()}`" + ) + + for forbidden_dispatcher_alias in ( + "def nativeCallDispatcherAgreesWithEvmYulLean ", + "def nativeDispatcherBlockAgreesWithEvmYulLean ", + "def nativeDispatcherExecAgreesWithEvmYulLean ", + "def nativeDispatcherExecAgreesWithEvmYulLeanPositive ", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanPositive_of_exec_ok_agree ", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanPositive_of_exec_yulHalt_agree ", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanPositive_of_exec_yulHalt_project_eq_agree ", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanPositive_of_exec_error_agree ", + "theorem nativeDispatcherExecAgreesWithEvmYulLeanPositive_of_exec_error_project_eq_agree ", + "theorem nativeDispatcherExecAgreesWithEvmYulLean_of_positive ", + "theorem nativeDispatcherExecAgreesWithEvmYulLean_of_exec_ok_agree ", + "theorem nativeDispatcherExecAgreesWithEvmYulLean_of_exec_yulHalt_agree ", + "theorem nativeDispatcherExecAgreesWithEvmYulLean_of_exec_error_agree ", + "theorem nativeDispatcherBlockAgreesWithEvmYulLean_of_exec_agree ", + "theorem nativeCallDispatcherAgreesWithEvmYulLean_of_dispatcherBlock_agree ", + ): + if forbidden_dispatcher_alias in normalized_end_to_end: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not reintroduce the hidden " + "native dispatcher fuel-wrapper alias " + f"`{forbidden_dispatcher_alias.strip()}`" + ) + + for forbidden_positive_alias in ( + "theorem layer3_contract_preserves_semantics_native_of_generated_dispatcherExec_positive ", + "theorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive ", + ): + if forbidden_positive_alias in normalized_end_to_end: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not reintroduce the " + "misleading positive dispatcher-exec compatibility alias " + f"`{forbidden_positive_alias.removeprefix('theorem ').strip()}`; " + "use the explicit `_positive_match` theorem name" + ) + + for forbidden_simple_storage_bridge_surface in ( + "def simpleStorageNativeCallDispatcherBridge ", + "def simpleStorageNativeRetrieveHitBridge ", + "def simpleStorageNativeStoreHitBridge ", + "def simpleStorageNativeSelectorMissBridge ", + "theorem simpleStorageNativeRetrieveHitBridge_proved ", + "theorem simpleStorageNativeStoreHitBridge_proved ", + "theorem simpleStorageNativeSelectorMissBridge_proved ", + "theorem simpleStorageNativeCallDispatcherBridge_of_per_case ", + ): + if forbidden_simple_storage_bridge_surface in normalized_end_to_end: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not reintroduce the " + "obsolete SimpleStorage fuel-wrapper bridge surface " + f"`{forbidden_simple_storage_bridge_surface.strip()}`" + ) + + for private_simple_storage_scaffold in ( + "simpleStorageNativeDispatcherStmts", + "simpleStorageNativeDispatcherInnerStmts", + "simpleStorageNativeDispatcher_letValue", + "simpleStorageNativeDispatcher_if1Cond", + "simpleStorageNativeDispatcher_if1Body", + "simpleStorageNativeDispatcher_if2Cond", + "simpleStorageNativeDispatcher_if2Body", + "simpleStorageNativeDispatcherFuel", + ): + if re.search( + r"^\s*(?:noncomputable\s+)?def\s+" + + re.escape(private_simple_storage_scaffold) + + r"\b", + end_to_end_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep SimpleStorage native " + "dispatcher proof scaffolding file-local; do not export " + f"`{private_simple_storage_scaffold}`" + ) + + if re.search( + r"^\s*def\s+SourceBodyNativeClosure\b", + end_to_end_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep " + "`SourceBodyNativeClosure` file-local; public callDispatcher " + "theorems should not export body-closure proof scaffolding" + ) + + for forbidden_reference_oracle_seam in ( + "theorem layer3_contract_preserves_semantics_via_reference_oracle ", + "theorem layer3_contract_preserves_semantics_via_reference_oracle_with_function_bridge ", + "theorem layers2_3_ir_matches_yul_via_reference_oracle ", + "theorem simpleStorage_endToEnd_via_reference_oracle ", + ): + if forbidden_reference_oracle_seam in normalized_end_to_end: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not reintroduce the " + "legacy Verity-backed public entry point " + f"`{forbidden_reference_oracle_seam.strip()}`" + ) + + for forbidden_public_alias in ( + "theorem layer3_contract_preserves_semantics ", + "theorem simpleStorage_endToEnd ", + ): + if forbidden_public_alias in normalized_end_to_end: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not reintroduce hidden " + "default-fuel public theorem alias " + f"`{forbidden_public_alias.strip()}`" + ) + + simple_storage_native_name = "simpleStorage_endToEnd_native_evmYulLean" + simple_storage_native_signature = theorem_signature( + end_to_end_text, + simple_storage_native_name, + ) + simple_storage_native_marker = f"theorem {simple_storage_native_name} " + simple_storage_native_start = normalized_end_to_end.find(simple_storage_native_marker) + if simple_storage_native_start < 0 or not simple_storage_native_signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean must keep the public native " + "`simpleStorage_endToEnd_native_evmYulLean` theorem explicit" + ) + else: + next_theorem = normalized_end_to_end.find( + " theorem ", + simple_storage_native_start + len(simple_storage_native_marker), + ) + simple_storage_native_span = ( + normalized_end_to_end[simple_storage_native_start:] + if next_theorem < 0 + else normalized_end_to_end[simple_storage_native_start:next_theorem] + ) + for required_direct_target in ( + "nativeGeneratedCallDispatcherResultOf", + "simpleStorageNativeCallDispatcherMatchBridge_of_per_case", + ): + if required_direct_target not in simple_storage_native_span: + errors.append( + "Compiler/Proofs/EndToEnd.lean public native SimpleStorage " + "theorem must consume the direct native callDispatcher " + f"target `{required_direct_target}`" + ) + if "nativeGeneratedCallDispatcherResultOf" not in simple_storage_native_signature: + errors.append( + "Compiler/Proofs/EndToEnd.lean public native SimpleStorage " + "theorem signature must target direct projected " + "`nativeGeneratedCallDispatcherResultOf` execution" + ) + for forbidden_compat_target in ( + "interpretIRRuntimeNative", + "simpleStorage_endToEnd_native_evmYulLean_interpretIRRuntimeNative", + "simpleStorage_endToEnd_native_evmYulLean_of_lowered_runtime_dispatcherStmts_match", + "simpleStorage_endToEnd_native_evmYulLean_of_positive_dispatcherExec_bridge", + "simpleStorageNativeCallDispatcherBridge_of_per_case", + ): + if ( + forbidden_compat_target in simple_storage_native_span + or forbidden_compat_target in simple_storage_native_signature + ): + errors.append( + "Compiler/Proofs/EndToEnd.lean public native SimpleStorage " + "theorem must not consume the compatibility dispatcher " + f"bridge `{forbidden_compat_target}`" + ) + for required_fuel_surface in ( - "def interpretYulRuntimeWithBackendFuel", - "theorem interpretYulRuntimeWithBackend_eq_fuel", + "private def execYulFuelWithBackend", + "private noncomputable def interpretYulRuntimeWithBackend", ): if required_fuel_surface not in normalized_retarget: errors.append( "Compiler/Proofs/YulGeneration/Backends/" - "EvmYulLeanRetarget.lean must keep the fuel-aligned " - f"interpreter oracle surface `{required_fuel_surface}` explicit" + "EvmYulLeanRetarget.lean must keep the backend-parameterized " + f"EVMYulLean interpreter surface `{required_fuel_surface}` " + "explicit but private" + ) + + for public_fuel_surface in ( + "backends_agree_on_bridged_builtins", + "evalYulExprWithBackend_eq_on_bridged", + "evalYulExpr_evmYulLean_eq_on_bridged", + "bridgedExpr_selectorExpr", + "evalYulExprWithBackend_evmYulLean_selectorExpr_semantics", + "execYulFuelWithBackend", + "execYulFuelWithBackend_verity_eq", + "execYulFuelWithBackend_let_eq_on_bridged", + "execYulFuelWithBackend_assign_eq_on_bridged", + "execYulFuelWithBackend_eq_on_bridged_straight_stmts", + "execYulFuelWithBackend_block_eq_on_bridged_straight_stmts", + "execYulFuelWithBackend_if_eq_on_bridged_body", + "execYulFuelWithBackend_switch_eq_on_bridged_cases", + "execYulFuelWithBackend_for_eq_on_bridged_parts", + "execYulFuelWithBackend_eq_on_bridged_target", + "execYulFuelWithBackend_eq_on_bridged_stmt", + "execYulFuelWithBackend_eq_on_bridged_stmts", + "emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies", + "execYulStmtsWithBackend", + "interpretYulRuntimeWithBackend", + "interpretYulRuntimeWithBackend_verity_eq", + "interpretYulFromIR_evmYulLean_eq_on_bridged_bodies", + ): + if re.search( + r"^\s*(?:noncomputable\s+)?(?:def|theorem)\s+" + + re.escape(public_fuel_surface) + + r"\b", + retarget_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean " + "must keep backend-interpreter transition surface " + f"`{public_fuel_surface}` private" + ) + + for forbidden_fuel_alias in ( + "def interpretYulRuntimeEvmYulLeanFuel ", + "def interpretYulRuntimeEvmYulLean ", + "theorem interpretYulRuntimeEvmYulLean_eq_backend ", + ): + if forbidden_fuel_alias in normalized_retarget: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/" + "EvmYulLeanRetarget.lean must not reintroduce hidden " + f"EVMYulLean fuel-wrapper alias `{forbidden_fuel_alias.strip()}`" ) forbidden_native_in_end_to_end = ( @@ -200,13 +1534,50 @@ def check_public_theorem_target( "def generatedRuntimeFunctionNamesUnique", "def generatedRuntimeDispatcherHasNoFuncDefs", "def generatedRuntimeFunctionBodiesHaveNoNestedFuncDefs", + "def buildSwitchSourceCases", + "theorem buildSwitchSourceCases_eq_switchCases", + "theorem lowerSwitchCasesNativeWithSwitchIds_find?_some_of_find_function", + "theorem lowerSwitchCasesNativeWithSwitchIds_find?_none_of_find_function", + "theorem lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_some_of_find_function", + "theorem lowerSwitchCasesNativeWithSwitchIds_buildSwitch_find?_none_of_find_function", + "theorem lowerRuntimeContractNative_single_stmt_eq_lowerStmtsNative", + "theorem lowerRuntimeContractNative_emitYul_noMapping_ok_dispatcher", + "theorem lowerStmtsNative_single_block_ok_singleton", + "theorem lowerStmtsNative_block_stmts_eq", + "theorem lowerStmtsNativeWithSwitchIds_let_head_eq", + "theorem lowerStmtsNativeWithSwitchIds_if_head_eq", + "theorem lowerStmtsNativeWithSwitchIds_singleton_switch_eq", + "theorem lowerStmtsNativeWithSwitchIds_revert_zero_zero", + "theorem lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq", + "theorem lowerStmtsNativeWithSwitchIds_singleton_switch_revert_default_eq_sourceLowered", + "theorem buildSwitch_noFallback_noReceive_lowered_inner_sourceLowered", + "theorem buildSwitch_noFallback_noReceive_lowered_inner_find?_some_of_find_function", + "theorem buildSwitch_noFallback_noReceive_lowered_inner_find?_none_of_find_function", "theorem NativeBlockPreservesWord_singleton", "theorem NativeBlockPreservesWord_of_forall_stmt", "theorem NativeBlockPreservesWord_of_forall_stmt_write_not_mem", "theorem NativeStmtPreservesWord_block", + "theorem exec_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq", + "theorem contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_hit_error_projectResult_eq", + "theorem exec_lowerNativeSwitchBlock_selector_find_hit_error_store_projectResult_eq", + "theorem exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq", + "theorem contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_none_with_revert_default_projectResult_eq", + "theorem exec_lowerNativeSwitchBlock_selector_find_none_with_revert_default_store_projectResult_eq", + "theorem exec_block_lowerNativeSwitchBlock_revert_default_hasSelectorState_projectResult_eq", + "theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_error_projectResult_eq", + "theorem exec_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq", + "theorem exec_lowerNativeSwitchBlock_selector_find_hit_ok_store_projectResult_eq", + "theorem exec_block_lowerNativeSwitchBlock_selector_find_hit_hasSelectorState_ok_projectResult_eq", + "theorem contractDispatcherExecResult_block_lowerNativeSwitchBlock_selector_find_hit_ok_projectResult_eq", "theorem NativeStmtPreservesWord_if_of_eval_self", "theorem NativeStmtPreservesWord_if_of_eval_preserves", "theorem NativeStmtPreservesWord_if_of_cond_preserves", + "theorem nativeSwitchBranchFold_ok_preserves_word", + "theorem execSwitchCases_ok_branch_preserves_word", + "theorem NativeStmtPreservesWord_switch_of_eval_preserves", + "theorem NativeStmtPreservesWord_switch_of_cond_preserves", + "theorem NativeStmtPreservesWord_switch_of_cond_preserves_and_nativeStmtsWriteNames_not_mem", + "theorem NativeStmtPreservesWord_switch_of_eval_preserves_and_nativeStmtsWriteNames_not_mem", "theorem NativeStmtPreservesWord_lowerAssignNative_lit_of_ne", "theorem NativeStmtPreservesWord_lowerAssignNative_hex_of_ne", "theorem NativeStmtPreservesWord_lowerAssignNative_ident_of_ne", @@ -220,6 +1591,8 @@ def check_public_theorem_target( "theorem NativeStmtPreservesWord_let_lowerExprNative_ident_of_not_mem", "theorem NativeStmtPreservesWord_let_prim_of_evalArgs_primCall_preserves", "theorem NativeStmtPreservesWord_let_user_of_evalArgs_call_preserves", + "theorem NativeStmtPreservesWord_let_prim_of_nativeEvalArgs_primCall_preserves", + "theorem NativeStmtPreservesWord_let_user_of_nativeEvalArgs_call_preserves", "theorem NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves", "theorem NativeStmtPreservesWord_let_lowerExprNative_call_userFunction_of_evalArgs_call_preserves", "theorem NativeStmtPreservesWord_let_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves", @@ -306,41 +1679,85 @@ def check_public_theorem_target( "theorem NativeExprPreservesWord_lowerExprNative_str", "theorem NativeExprPreservesWord_lowerExprNative_ident", "theorem NativeExprPreservesWord_call_prim_of_evalArgs_primCall_preserves", + "theorem NativeExprPreservesWord_call_prim_of_nativeEvalArgs_primCall_preserves", "theorem NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves", + "theorem NativeExprPreservesWord_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves", "theorem NativeExprPreservesWord_call_user_of_evalArgs_call_preserves", + "theorem NativeExprPreservesWord_call_user_of_nativeEvalArgs_call_preserves", "theorem NativeExprPreservesWord_lowerExprNative_call_userFunction_of_evalArgs_call_preserves", + "theorem NativeExprPreservesWord_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves", + "inductive NativeMappingFreeBridgedExpr", + "theorem NativeExprPreservesWord_lowerExprNative_of_mappingFreeBridgedExpr", + "theorem NativeEvalArgsPreservesWord_lowerExprNative_reverse_of_mappingFreeBridgedExprs", + "inductive NativeMappingFreePreservableStraightStmt", + "def NativeMappingFreeSideConditionForBridgedExpr", + "theorem NativeMappingFreeBridgedExpr.of_bridgedExpr", + "def NativeMappingFreeSideConditionForBridgedStraightStmt", + "theorem NativeMappingFreePreservableStraightStmt.of_bridgedStraightStmt", + "theorem NativeMappingFreePreservableStraightStmts.of_bridgedStraightStmts", + "theorem NativeStmtPreservesWord_lowerStmtGroupNativeWithSwitchIds_of_mappingFreePreservableStraightStmt", + "theorem NativeStmtPreservesWord_of_mem_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts", + "theorem NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts", "theorem NativeStmtPreservesWord_exprStmtCall_prim_of_evalArgs_primCall_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_user_of_evalArgs_call_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_prim_of_nativeEvalArgs_primCall_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_user_of_nativeEvalArgs_call_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_runtimePrimOp_of_evalArgs_primCall_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_userFunction_of_evalArgs_call_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_runtimePrimOp_of_nativeEvalArgs_primCall_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_call_userFunction_of_nativeEvalArgs_call_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_mstore_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_mstore_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_mstore8_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_mstore8_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_mstore8_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_sstore_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_sstore_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_sstore_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_tstore_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_tstore_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_tstore_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_calldatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_calldatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_returndatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_returndatacopy_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_log0_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_log0_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log0_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_log1_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_log1_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log1_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_log2_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_log2_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log2_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_log3_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_log3_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log3_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_log4_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_log4_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_log4_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_return_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_return_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_return_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_revert_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_revert_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_evalArgs_preserves", + "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_revert_of_nativeEvalArgs_and_evalArgs_shape_preserves", "theorem NativeStmtPreservesWord_exprStmtCall_stop", "theorem NativeStmtPreservesWord_exprStmtCall_lowerExprNative_stop", "theorem nativeStmtWriteNames_not_mem_of_nativeStmtsWriteNames_not_mem", @@ -426,6 +1843,689 @@ def check_native_switch_lowering_boundary(native_adapter_text: str, native_smoke return errors +def check_default_builtin_backend(builtins_text: str) -> list[str]: + """Pin the file-local default backend to EVMYulLean. + + The backend aliases are transition/reference-oracle helpers, not public + proof authority. Keep them private while ensuring unqualified builtin + evaluation does not silently drift back to the Verity backend. + """ + + errors: list[str] = [] + normalized = normalize_ws(builtins_text) + required = ( + "private abbrev legacyBuiltinBackend : BuiltinBackend := .verity", + "private abbrev defaultBuiltinBackend : BuiltinBackend := .evmYulLean", + "private def evalBuiltinCall", + "theorem defaultBuiltinBackend_eq_evmYulLean", + ) + for snippet in required: + if normalize_ws(snippet) not in normalized: + errors.append( + "Compiler/Proofs/YulGeneration/ReferenceOracle/Builtins.lean " + "must pin private reference-oracle/default builtin backend " + f"aliases with `{snippet}`" + ) + return errors + + +def check_reference_oracle_names( + end_to_end_text: str, retarget_text: str, preservation_text: str +) -> list[str]: + """Keep legacy Layer-3 reference-oracle entry points explicitly named.""" + + errors: list[str] = [] + normalized_end_to_end = normalize_ws(end_to_end_text) + normalized_retarget = normalize_ws(retarget_text) + normalized_preservation = normalize_ws(preservation_text) + + if re.search(r"\btheorem\s+yulCodegen_preserves_semantics(?!_)", preservation_text): + errors.append( + "Compiler/Proofs/YulGeneration/Preservation.lean must not expose the " + "legacy reference-oracle theorem as bare `yulCodegen_preserves_semantics`; " + "use `yulCodegen_preserves_semantics_via_reference_oracle`" + ) + + if "private theorem yulCodegen_preserves_semantics_via_reference_oracle" not in normalized_preservation: + errors.append( + "Compiler/Proofs/YulGeneration/Preservation.lean must keep the legacy " + "Layer-3 oracle theorem explicitly named but private " + "`yulCodegen_preserves_semantics_via_reference_oracle`" + ) + + if re.search( + r"^\s*theorem\s+yulCodegen_preserves_semantics_via_reference_oracle\b", + preservation_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/YulGeneration/Preservation.lean must not expose " + "`yulCodegen_preserves_semantics_via_reference_oracle` as public " + "proof authority" + ) + + if "yulCodegen_preserves_semantics_via_reference_oracle" in normalized_retarget: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean must " + "not invoke the private legacy Layer-3 oracle theorem " + "`yulCodegen_preserves_semantics_via_reference_oracle`" + ) + + for public_legacy_retarget in ( + "yulCodegen_preserves_semantics_evmYulLeanBackend", + "yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle", + ): + if re.search( + r"^\s*(?:private\s+)?theorem\s+" + + re.escape(public_legacy_retarget) + + r"\b", + retarget_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean " + "must not retain transition-only legacy Layer-3 retarget theorem " + f"`{public_legacy_retarget}`" + ) + + if "theorem yulCodegen_preserves_semantics_evmYulLean " in normalized_retarget: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean must " + "not reintroduce the hidden reference-oracle compatibility alias " + "`yulCodegen_preserves_semantics_evmYulLean`; use the explicit " + "`yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle` name" + ) + + if "theorem yulCodegen_preserves_semantics_evmYulLean_via_reference_oracle " in normalized_retarget: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanRetarget.lean must " + "not reintroduce the hidden default-fuel compatibility alias " + "`yulCodegen_preserves_semantics_evmYulLean_via_reference_oracle`; " + "use the explicit " + "`yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle` name" + ) + + if "yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle" in normalized_end_to_end: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not mention the legacy " + "compatibility alias " + "`yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle`" + ) + + for forbidden_end_to_end_legacy_term in ( + "evalBuiltinCall", + "legacyEvalBuiltinCallWithContext", + "legacyBuiltinBackend", + "Compiler.Proofs.YulGeneration.ReferenceOracle", + "interpretYulRuntimeWithBackend", + "execYulFuelWithBackend", + "defaultBuiltinBackend", + "BuiltinBackend", + ): + if forbidden_end_to_end_legacy_term in end_to_end_text: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not directly mention " + "legacy oracle/backend term " + f"`{forbidden_end_to_end_legacy_term}`; keep those dependencies " + "isolated below the public EndToEnd surface" + ) + + for removed_native_reference_alias in ( + "theorem layer3_contract_preserves_semantics_native_via_reference_oracle_of_evmYulLean_bridge", + "theorem layers2_3_ir_matches_native_evmYulLean_via_reference_oracle_of_evmYulLean_bridge", + ): + if removed_native_reference_alias in normalized_end_to_end: + errors.append( + "Compiler/Proofs/EndToEnd.lean must not reintroduce the removed " + "generic native reference-oracle/fuel-wrapper seam " + f"`{removed_native_reference_alias.removeprefix('theorem ')}`" + ) + + return errors + + +def check_legacy_proof_boundary( + public_boundary_files: list[tuple[str, str]], + legacy_proof_files: list[tuple[str, str]], +) -> list[str]: + """Keep transition-only legacy proof modules below the native public path.""" + + errors: list[str] = [] + + for label, text in public_boundary_files: + for module in TRANSITION_ONLY_PUBLIC_FORBIDDEN_MODULES: + import_line = f"import {module}" + if import_line in text: + errors.append( + f"{label} must not import transition-only legacy proof " + f"module `{module}`" + ) + if "import Compiler.Proofs.YulGeneration.ReferenceOracle" in text: + errors.append( + f"{label} must not import legacy ReferenceOracle modules; " + "keep the custom Yul interpreter below the native public path" + ) + + public_decl_pattern = re.compile( + r"^\s*(?:@\[[^\]]*\]\s*)*" + r"(?!(?:private|namespace|end|open|section|variable|include|omit|attribute)\b)" + r"(def|theorem|lemma|abbrev|inductive|structure)\s+([A-Za-z0-9_'.]+)\b", + re.MULTILINE, + ) + for label, text in legacy_proof_files: + for match in public_decl_pattern.finditer(text): + errors.append( + f"{label} must not expose transition-only legacy declaration " + f"`{match.group(2)}` as public proof authority" + ) + + return errors + + +def check_yul_generation_readme(text: str) -> list[str]: + """Keep the Layer 3 README aligned with the native dispatcher retarget.""" + + errors: list[str] = [] + required_snippets = ( + "Legacy reference-oracle stack complete", + "`EvmYul.Yul.callDispatcher` theorem stack", + "not the fuel-parametric proof-interpreter preservation theorem", + "**`Preservation.lean`** - Legacy Layer 3 preservation theorem", + "**`Backends/EvmYulLeanNativeHarness.lean`** - Native EVMYulLean execution", + "**`Backends/EvmYulLeanRetarget.lean`** - Bridged-fragment backend equivalence", + "Does not export contract-level proof-interpreter preservation as public", + ) + for snippet in required_snippets: + if snippet not in text: + errors.append( + "Compiler/Proofs/YulGeneration/README.md must describe the " + f"native dispatcher retarget boundary with `{snippet}`" + ) + forbidden_snippets = ( + "**Status**: Complete (PR #42)", + "**`Preservation.lean`** - Main Layer 3 preservation theorem", + ) + for snippet in forbidden_snippets: + if snippet in text: + errors.append( + "Compiler/Proofs/YulGeneration/README.md must not describe the " + f"legacy proof-interpreter path as current public authority: `{snippet}`" + ) + return errors + + +def lean_module_to_path(module: str) -> Path | None: + path = ROOT / (module.replace(".", "/") + ".lean") + if path.exists(): + return path + return None + + +def lean_imports(text: str) -> list[str]: + imports: list[str] = [] + for line in text.splitlines(): + stripped = line.strip() + if stripped.startswith("import "): + parts = stripped.split() + if len(parts) >= 2: + imports.append(parts[1]) + return imports + + +def check_transition_only_import_allowlist( + lean_files: list[tuple[str, str]], +) -> list[str]: + """Keep transition-only ReferenceOracle imports out of new proof modules.""" + + errors: list[str] = [] + forbidden_bridge_import = ( + "Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeLemmas" + ) + bridge_allowlist = set(BRIDGE_LEMMAS_IMPORT_ALLOWLIST) + reference_oracle_import_prefix = ( + "Compiler.Proofs.YulGeneration.ReferenceOracle" + ) + reference_oracle_allowlist = set(REFERENCE_ORACLE_IMPORT_ALLOWLIST) + for label, text in lean_files: + imports = lean_imports(text) + if label not in bridge_allowlist and forbidden_bridge_import in imports: + errors.append( + f"{label} must not import transition-only bridge lemma module " + f"`{forbidden_bridge_import}`; keep ReferenceOracle bridge evidence " + "confined to EvmYulLeanRetarget and bridge regression tests" + ) + if label not in reference_oracle_allowlist: + for imported in imports: + if imported == reference_oracle_import_prefix or imported.startswith( + reference_oracle_import_prefix + "." + ): + errors.append( + f"{label} must not import legacy ReferenceOracle module " + f"`{imported}`; keep the custom interpreter confined " + "to the known transition and regression-test modules" + ) + return errors + + +def transition_import_scan_files() -> list[Path]: + files = [ROOT / "PrintAxioms.lean"] + for directory in (ROOT / "Compiler", ROOT / "Contracts"): + if directory.exists(): + files.extend(sorted(directory.rglob("*.lean"))) + return files + + +def check_public_transitive_import_boundary( + public_boundary_files: list[tuple[str, str]], +) -> list[str]: + """Reject transitive legacy imports from native public boundary modules.""" + + errors: list[str] = [] + forbidden_modules = TRANSITION_ONLY_PUBLIC_FORBIDDEN_MODULES + ( + "Compiler.Proofs.YulGeneration.ReferenceOracle", + ) + text_overrides = { + label: text + for label, text in public_boundary_files + } + + for label, text in public_boundary_files: + queue: list[tuple[str, str, list[str]]] = [(label, text, [label])] + seen_modules: set[str] = set() + while queue: + current_label, current_text, chain = queue.pop(0) + for imported in lean_imports(current_text): + if any( + imported == forbidden or imported.startswith(forbidden + ".") + for forbidden in forbidden_modules + ): + errors.append( + f"{label} must not transitively import transition-only " + f"legacy proof module `{imported}` via " + + " -> ".join(chain + [imported]) + ) + continue + + if imported in seen_modules: + continue + seen_modules.add(imported) + + imported_path = lean_module_to_path(imported) + if imported_path is None: + continue + try: + imported_relative = imported_path.relative_to(ROOT).as_posix() + except ValueError: + continue + if not imported_relative.startswith("Compiler/"): + continue + imported_text = text_overrides.get( + imported_relative, + imported_path.read_text(encoding="utf-8"), + ) + queue.append((imported_relative, imported_text, chain + [imported])) + + return errors + + +def check_public_transitive_forbidden_terms( + public_boundary_files: list[tuple[str, str]], +) -> list[str]: + """Reject legacy proof-interpreter/backend names in public reachable files.""" + + errors: list[str] = [] + forbidden_terms = ( + "ReferenceOracle", + "execYulFuel", + "interpretYulRuntimeWithBackend", + ".verity", + "defaultBuiltinBackend", + "legacyBuiltinBackend", + "evalBuiltinCallWithContext", + "nativeIRRuntimeAgreesWithInterpreter", + ) + text_overrides = { + label: text + for label, text in public_boundary_files + } + + for label, text in public_boundary_files: + queue: list[tuple[str, str, list[str]]] = [(label, text, [label])] + seen_labels: set[str] = set() + while queue: + current_label, current_text, chain = queue.pop(0) + if current_label in seen_labels: + continue + seen_labels.add(current_label) + + for forbidden in forbidden_terms: + if forbidden in current_text: + errors.append( + f"{label} must not transitively expose legacy " + f"proof-interpreter/backend term `{forbidden}` via " + + " -> ".join(chain) + ) + + for imported in lean_imports(current_text): + imported_path = lean_module_to_path(imported) + if imported_path is None: + continue + try: + imported_relative = imported_path.relative_to(ROOT).as_posix() + except ValueError: + continue + if not imported_relative.startswith("Compiler/"): + continue + imported_text = text_overrides.get( + imported_relative, + imported_path.read_text(encoding="utf-8"), + ) + queue.append((imported_relative, imported_text, chain + [imported])) + + return errors + + +def check_bridge_lemmas_transition_surface(bridge_lemmas_text: str) -> list[str]: + """Keep transition-helper bridge rewrites out of the public theorem surface.""" + + errors: list[str] = [] + if re.search( + r"^\s*theorem\s+evalBuiltinCallWithBackendContext_evmYulLean_pure_bridge\b", + bridge_lemmas_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgeLemmas.lean " + "must keep transition-only routing helper " + "`evalBuiltinCallWithBackendContext_evmYulLean_pure_bridge` private" + ) + return errors + + +def check_adapter_correctness_transition_surface(adapter_correctness_text: str) -> list[str]: + """Keep legacy adapter-correctness rewrites out of the public theorem surface.""" + + errors: list[str] = [] + for helper in ( + "assign_equiv_let", + "assign_equiv_let'", + "legacyExecYulFuel_stmts_nil", + "for_init_hoist", + "for_init_hoist_revert", + "for_init_hoist_return", + "for_init_hoist_stop", + ): + if re.search( + r"^\s*(?:@\[[^\]]*\]\s*)*theorem\s+" + + re.escape(helper) + + r"\b", + adapter_correctness_text, + re.MULTILINE, + ): + errors.append( + "Compiler/Proofs/YulGeneration/Backends/" + "EvmYulLeanAdapterCorrectness.lean must keep transition-only " + f"adapter correctness helper `{helper}` private" + ) + return errors + + +def check_native_closure_import_boundary( + bridge_predicates_text: str, + body_closure_text: str, + source_expr_closure_text: str, +) -> list[str]: + """Keep native closure predicates isolated from legacy retarget proofs.""" + + errors: list[str] = [] + + if "import Compiler.Proofs.YulGeneration.ReferenceOracle" in bridge_predicates_text: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/" + "EvmYulLeanBridgePredicates.lean must not import ReferenceOracle; " + "native closure predicates should remain syntactic" + ) + + if "import Compiler.Proofs.YulGeneration.LogNames" not in bridge_predicates_text: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/" + "EvmYulLeanBridgePredicates.lean must import the neutral " + "Yul log-name helper" + ) + + if "import Compiler.Proofs.IRGeneration.IRInterpreter" in bridge_predicates_text: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/" + "EvmYulLeanBridgePredicates.lean must not import the full IR " + "interpreter for log-name predicates" + ) + + for forbidden_predicate_surface in ( + "legacy Yul reference oracle", + "legacy retarget executor", + "legacy context evaluator", + "native and transition backends", + ".verity", + ): + if forbidden_predicate_surface in bridge_predicates_text: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/" + "EvmYulLeanBridgePredicates.lean must describe the generated " + "fragment in native-closure terms, not legacy transition " + f"authority language `{forbidden_predicate_surface}`" + ) + + for label, text in ( + ("EvmYulLeanBodyClosure.lean", body_closure_text), + ("EvmYulLeanSourceExprClosure.lean", source_expr_closure_text), + ): + if "import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgePredicates" not in text: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/" + f"{label} must import the neutral EVMYulLean bridge predicates" + ) + for forbidden_import in ( + "import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanRetarget", + "import Compiler.Proofs.YulGeneration.Preservation", + "import Compiler.Proofs.YulGeneration.ReferenceOracle", + ): + if forbidden_import in text: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/" + f"{label} must not import legacy transition proof authority " + f"`{forbidden_import.removeprefix('import ')}`" + ) + + for required_source_expr_theorem in ( + "theorem bridgedSourceExpr_of_exprCompileCore", + "theorem bridgedSourceExpr_keccak256_of_exprCompileCore", + "theorem compileExpr_keccak256_bridgedSource_of_exprCompileCore", + "theorem compileExpr_mappingChain_bridgedSource", + "private theorem bridgedExpr_sload_lit", + "| arrayLength (name : String) : BridgedSourceExpr (.arrayLength name)", + "| builtinExp {base exponent}", + "| storage (fieldName : String) : BridgedSourceExpr (.storage fieldName)", + "| storageAddr (fieldName : String) : BridgedSourceExpr (.storageAddr fieldName)", + "| storageArrayLength (fieldName : String) :", + "| adtTag (adtName storageField : String) :", + "| adtField (adtName variantName fieldName : String) (fieldIndex : Nat)", + "| mapping {key : Expr} (fieldName : String) (hKey : BridgedSourceExpr key)", + "| mappingWord {key : Expr} (fieldName : String) (hKey : BridgedSourceExpr key)", + "| mappingUint {key : Expr} (fieldName : String) (hKey : BridgedSourceExpr key)", + "| mapping2 {key1 key2 : Expr} (fieldName : String)", + "| mapping2Word {key1 key2 : Expr} (fieldName : String)", + "| structMember {key : Expr} (fieldName : String) (hKey : BridgedSourceExpr key)", + "| structMember2 {key1 key2 : Expr} (fieldName : String)", + "private theorem compileMappingSlotRead_bridged", + "private theorem bridgedExpr_sload_mappingSlot2_lit", + "private theorem bridgedExpr_sload_mappingSlotChain_lit", + "private theorem bridgedExpr_packed_read", + ): + if required_source_expr_theorem not in source_expr_closure_text: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/" + "EvmYulLeanSourceExprClosure.lean must keep the native " + "source-expression closure theorem " + f"`{required_source_expr_theorem.removeprefix('theorem ')}`" + ) + + for required_body_closure_theorem in ( + "theorem bridgedSafeStmts_letKeccak_of_exprCompileCore", + "theorem bridgedSafeStmts_assignKeccak_of_exprCompileCore", + "theorem bridgedSafeStmts_externalMstoreLetKeccak_of_exprCompileCore", + ): + if required_body_closure_theorem not in body_closure_text: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/" + "EvmYulLeanBodyClosure.lean must keep the native safe-body " + "keccak binding closure theorem " + f"`{required_body_closure_theorem.removeprefix('theorem ')}`" + ) + + return errors + + +def check_runtime_types_import_boundary(runtime_types_text: str) -> list[str]: + """Keep shared Yul runtime plumbing from importing IR execution semantics.""" + + errors: list[str] = [] + if "import Compiler.Proofs.IRGeneration.IRInterpreter" in runtime_types_text: + errors.append( + "Compiler/Proofs/YulGeneration/RuntimeTypes.lean must import " + "IRRuntimeTypes rather than the full IR interpreter" + ) + if "import Compiler.Proofs.IRGeneration.IRRuntimeTypes" not in runtime_types_text: + errors.append( + "Compiler/Proofs/YulGeneration/RuntimeTypes.lean must import the " + "neutral IR runtime record module" + ) + return errors + + +def check_native_harness_import_boundary(native_harness_text: str) -> list[str]: + """Keep the native harness independent of the full IR interpreter.""" + + errors: list[str] = [] + if "import Compiler.Proofs.IRGeneration.IRInterpreter" in native_harness_text: + errors.append( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean " + "must consume IRRuntimeTypes records without importing the full IR " + "interpreter" + ) + return errors + + +def check_root_compiler_import_boundary(root_compiler_text: str) -> list[str]: + """Keep the root aggregate from directly re-exporting broad interpreters.""" + + errors: list[str] = [] + if "import Compiler.Proofs.IRGeneration.IRInterpreter" in root_compiler_text: + errors.append( + "Compiler.lean must not directly import the full IR interpreter; " + "import proof modules that own their semantic dependencies instead" + ) + return errors + + +def check_native_alias_signatures(end_to_end_text: str) -> list[str]: + """Reject hidden native dispatcher fuel-wrapper aliases in theorem signatures.""" + + errors: list[str] = [] + theorem_pattern = re.compile( + r"^\s*theorem\s+([A-Za-z0-9_']+)\b(.*?)(?=\s:=)", + re.DOTALL | re.MULTILINE, + ) + hidden_dispatcher_alias = re.compile( + r"\bnative(?:CallDispatcher|DispatcherBlock|DispatcherExec)" + r"AgreesWithEvmYulLean(?:Positive)?\b" + ) + + for match in theorem_pattern.finditer(end_to_end_text): + name = match.group(1) + signature = match.group(2) + hidden_matches = sorted(set(hidden_dispatcher_alias.findall(signature))) + if hidden_matches: + errors.append( + "Compiler/Proofs/EndToEnd.lean theorem " + f"`{name}` must expose explicit fuel-wrapper predicates instead " + "of hidden native dispatcher aliases: " + + ", ".join(f"`{hidden}`" for hidden in hidden_matches) + ) + + return errors + + +def check_public_end_to_end_theorem_signatures(end_to_end_text: str) -> list[str]: + """Reject legacy oracle/interpreter terms in public EndToEnd theorem APIs.""" + + errors: list[str] = [] + theorem_pattern = re.compile( + r"^\s*theorem\s+([A-Za-z0-9_']+)\b(.*?)(?=\s:=)", + re.DOTALL | re.MULTILINE, + ) + forbidden_signature_terms = ( + "ReferenceOracle", + "execYulFuel", + "execYulFuelWithBackend", + "interpretYulRuntimeWithBackend", + ".verity", + "defaultBuiltinBackend", + "legacyBuiltinBackend", + "evalBuiltinCallWithContext", + "nativeIRRuntimeAgreesWithInterpreter", + ) + public_call_dispatcher_theorems = ( + "compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match", + "compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping", + "compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping", + ) + forbidden_public_call_dispatcher_terms = ( + "SourceBodyNativeClosure", + "lowerRuntimeContractNative", + "nativeChainIdRepresentable", + "nativeBlobBaseFeeRepresentable", + "nativeRuntimePathUsesUnsupportedHeaderBuiltin", + ) + + for match in theorem_pattern.finditer(end_to_end_text): + name = match.group(1) + signature = match.group(2) + leaked_terms = sorted( + term for term in forbidden_signature_terms if term in signature + ) + if leaked_terms: + errors.append( + "Compiler/Proofs/EndToEnd.lean theorem " + f"`{name}` must expose native EVMYulLean theorem parameters " + "rather than legacy oracle/interpreter terms: " + + ", ".join(f"`{term}`" for term in leaked_terms) + ) + if re.search(r"\(\s*fuel'?\s*:\s*Nat\s*\)", signature): + errors.append( + "Compiler/Proofs/EndToEnd.lean theorem " + f"`{name}` must use canonical native generated-runtime fuel " + "instead of exposing arbitrary theorem-facing fuel" + ) + if name in public_call_dispatcher_theorems: + leaked_call_dispatcher_terms = sorted( + term + for term in forbidden_public_call_dispatcher_terms + if term in signature + ) + if leaked_call_dispatcher_terms: + errors.append( + "Compiler/Proofs/EndToEnd.lean public callDispatcher theorem " + f"`{name}` must keep body, full-runtime lowering, and " + "native environment-validation obligations below the " + "public direct callDispatcher signature: " + + ", ".join( + f"`{term}`" for term in leaked_call_dispatcher_terms + ) + ) + + return errors + + def check_unbridged_environment_boundary(native_harness_text: str, native_smoke_text: str) -> list[str]: """Keep the native environment-read limitation explicit and tested. @@ -470,6 +2570,7 @@ def check_unbridged_environment_boundary(native_harness_text: str, native_smoke_ 'nativeStoresBuiltinWithTx "blobbasefee" 16 EvmYul.MIN_BASE_FEE_PER_BLOB_GAS', 'nativeRejectsUnsupportedHeaderBuiltin "coinbase" = true', 'nativeRejectsUnsupportedHeaderBuiltin "gaslimit" = true', + 'nativeRejectsUnsupportedHeaderBuiltin "selfbalance" = true', 'nativeAllowsUnselectedUnsupportedEnvironmentBuiltin = true', ): if pinned_default not in normalized_native_smoke: @@ -487,14 +2588,40 @@ def main() -> int: if not DOC.exists(): print(f"Missing: {DOC.relative_to(ROOT)}", file=sys.stderr) return 1 - for path in (END_TO_END, NATIVE_HARNESS, RETARGET, NATIVE_ADAPTER, NATIVE_SMOKE_TEST): + if not DOD_DOC.exists(): + print(f"Missing: {DOD_DOC.relative_to(ROOT)}", file=sys.stderr) + return 1 + for path in ( + ROOT_COMPILER, + END_TO_END, + NATIVE_HARNESS, + RETARGET, + BRIDGE_PREDICATES, + BRIDGE_LEMMAS, + ADAPTER_CORRECTNESS, + BODY_CLOSURE, + SOURCE_EXPR_CLOSURE, + BUILTINS, + PRESERVATION, + NATIVE_ADAPTER, + NATIVE_SMOKE_TEST, + RUNTIME_TYPES, + *LEGACY_PROOF_FILES, + ): if not path.exists(): print(f"Missing: {path.relative_to(ROOT)}", file=sys.stderr) return 1 native_harness_text = NATIVE_HARNESS.read_text(encoding="utf-8") native_smoke_text = NATIVE_SMOKE_TEST.read_text(encoding="utf-8") + runtime_types_text = RUNTIME_TYPES.read_text(encoding="utf-8") errors = check_doc(DOC.read_text(encoding="utf-8")) + errors.extend( + check_definition_of_done_doc(DOD_DOC.read_text(encoding="utf-8")) + ) + errors.extend( + check_yul_generation_readme(YULGEN_README.read_text(encoding="utf-8")) + ) errors.extend( check_public_theorem_target( END_TO_END.read_text(encoding="utf-8"), @@ -502,6 +2629,144 @@ def main() -> int: RETARGET.read_text(encoding="utf-8"), ) ) + errors.extend( + check_default_builtin_backend(BUILTINS.read_text(encoding="utf-8")) + ) + errors.extend( + check_reference_oracle_names( + END_TO_END.read_text(encoding="utf-8"), + RETARGET.read_text(encoding="utf-8"), + PRESERVATION.read_text(encoding="utf-8"), + ) + ) + errors.extend( + check_native_closure_import_boundary( + BRIDGE_PREDICATES.read_text(encoding="utf-8"), + BODY_CLOSURE.read_text(encoding="utf-8"), + SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ) + ) + errors.extend(check_runtime_types_import_boundary(runtime_types_text)) + errors.extend(check_native_harness_import_boundary(native_harness_text)) + errors.extend( + check_root_compiler_import_boundary( + ROOT_COMPILER.read_text(encoding="utf-8") + ) + ) + errors.extend( + check_legacy_proof_boundary( + [ + ("Compiler.lean", ROOT_COMPILER.read_text(encoding="utf-8")), + ("Compiler/Proofs/EndToEnd.lean", END_TO_END.read_text(encoding="utf-8")), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean", + native_harness_text, + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean", + NATIVE_ADAPTER.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgePredicates.lean", + BRIDGE_PREDICATES.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean", + BODY_CLOSURE.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean", + SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ), + ], + [ + (path.relative_to(ROOT).as_posix(), path.read_text(encoding="utf-8")) + for path in LEGACY_PROOF_FILES + ], + ) + ) + errors.extend( + check_public_transitive_import_boundary( + [ + ("Compiler.lean", ROOT_COMPILER.read_text(encoding="utf-8")), + ("Compiler/Proofs/EndToEnd.lean", END_TO_END.read_text(encoding="utf-8")), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean", + native_harness_text, + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean", + NATIVE_ADAPTER.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgePredicates.lean", + BRIDGE_PREDICATES.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean", + BODY_CLOSURE.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean", + SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ), + ] + ) + ) + errors.extend( + check_public_transitive_forbidden_terms( + [ + ("Compiler.lean", ROOT_COMPILER.read_text(encoding="utf-8")), + ("Compiler/Proofs/EndToEnd.lean", END_TO_END.read_text(encoding="utf-8")), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean", + native_harness_text, + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean", + NATIVE_ADAPTER.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgePredicates.lean", + BRIDGE_PREDICATES.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean", + BODY_CLOSURE.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean", + SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ), + ] + ) + ) + errors.extend( + check_transition_only_import_allowlist( + [ + (path.relative_to(ROOT).as_posix(), path.read_text(encoding="utf-8")) + for path in transition_import_scan_files() + ] + ) + ) + errors.extend( + check_bridge_lemmas_transition_surface( + BRIDGE_LEMMAS.read_text(encoding="utf-8") + ) + ) + errors.extend( + check_adapter_correctness_transition_surface( + ADAPTER_CORRECTNESS.read_text(encoding="utf-8") + ) + ) + errors.extend( + check_native_alias_signatures(END_TO_END.read_text(encoding="utf-8")) + ) + errors.extend( + check_public_end_to_end_theorem_signatures( + END_TO_END.read_text(encoding="utf-8") + ) + ) errors.extend( check_unbridged_environment_boundary( native_harness_text, diff --git a/scripts/check_proof_length.py b/scripts/check_proof_length.py index d0d8e8287..4ab81383d 100644 --- a/scripts/check_proof_length.py +++ b/scripts/check_proof_length.py @@ -85,6 +85,15 @@ "compiledStmtStep_setMappingChain_singleSlot_of_slotSafety_preserves", "compiledStmtStep_setMappingPackedWord_singleSlot_of_slotSafety_preserves", "compiledStmtStep_setMappingPackedWord_singleSlot_of_slotSafety", + # Native selected-body handoff: splits generated switch-case freshness into + # the actual lowered user-body freshness used by the remaining native + # selected-body execution bridge. + "nativeGeneratedSelectedUserBodyMatchedFresh_of_switchFresh", + # Native selected-body handoff: packages compile-derived closure facts with + # switch-freshness-derived matched-flag freshness for the actual lowered + # user body. This deliberately stays private until the execution bridge is + # closed. + "selectedUserBodyClosureAndMatchedFresh_of_compile_ok_supported_switchFresh", # --- Helper-aware result packaging bridge --- "interpretFunctionWithHelpers_eq_execResultToIRResultWithInternals_of_body", "compiledStmtStep_setStructMember2_singleSlot_of_slotSafety_preserves", @@ -297,28 +306,21 @@ # Call-surface decomposition kept as one structural recursion proof. "stmtOrListTouchesUnsupportedCallSurface_eq_featureOr", # --- Yul generation / Layer 3 proofs --- - "yulCodegen_preserves_semantics", + "yulCodegen_preserves_semantics_via_reference_oracle", "stmt_and_stmts_equiv", "execIRStmtsFuel_equiv_execYulStmtsFuel_of_stmt_equiv", - "execYulFuel_succ_eq", + "legacyExecYulFuel_succ_eq", "exec_switchCaseBody_revert_of_short", "exec_switchCaseBody_continue_of_long", "SwitchCaseBodyBridge_short", "SwitchCaseBodyBridge", - "layer3_contract_preserves_semantics", # Thin EVMYulLean EndToEnd wrapper; signature carries explicit body-closure # witnesses and the proof mostly forwards existing Layer-3 hypotheses. - "layer3_contract_preserves_semantics_evmYulLean", + "layer3_contract_preserves_semantics_evmYulLeanBackend", # --- End-to-end proofs --- - "simpleStorage_endToEnd", # Thin public wrapper; the scanner counts the trailing Phase 4 summary # comment in its theorem span. - "simpleStorage_endToEnd_evmYulLean", - # Native public wrapper keeps the lowering equality, native environment - # validation, and callDispatcher bridge as explicit hypotheses so proof - # modules do not rely on VM computation; the body delegates to the lowered - # native Layer-3 theorem. - "simpleStorage_endToEnd_native_evmYulLean_of_callDispatcher_bridge", + "simpleStorage_endToEnd_evmYulLeanBackend", # Native SimpleStorage wrapper keeps the dispatcher-agreement seam explicit # while delegating to the lowered native theorem; the long span is the public # hypothesis surface, not a large proof script. @@ -343,21 +345,14 @@ # the chained `setMachineState` overrides to extract the 32-byte # `H_return` window before computing `projectHaltReturn`. "projectResult_retrieveHit_eq", - # Phase 2 retrieve-hit bridge closure: composes the closed-form IR result, - # native dispatcher halt endpoint, projected-storage preservation, and - # EVMYulLean Layer-3 result agreement under the public theorem hypotheses. - # Splitting would create several single-use helpers whose proofs are mostly - # repeated hypothesis plumbing around the same concrete retrieve path. - "simpleStorageNativeRetrieveHitBridge_proved", - # Phase 3 selector-miss bridge closure: composes the closed-form - # selector-miss IR result, native revert endpoint, and Layer-3 agreement - # under the public theorem hypotheses. Splitting would create single-use - # helpers that only forward the same selector-miss facts and fuel reshape. - "simpleStorageNativeSelectorMissBridge_proved", - # Phase 3 store-hit bridge closure: composes short-calldata revert and - # successful sstore/stop paths against Layer-3 EVMYulLean agreement, using - # the bounded-slot storage projection helper above. - "simpleStorageNativeStoreHitBridge_proved", + # Direct native-vs-IR retrieve-hit closure: intentionally mirrors the + # concrete native dispatcher halt and projected-storage plumbing above, but + # targets `nativeDispatcherExecMatchesIRPositive` directly. + "simpleStorageNativeRetrieveHitMatchBridge_proved", + # Direct native-vs-IR store-hit closure: it intentionally keeps the + # short-calldata revert and argument-present storage-update branches in one + # proof so the direct native case split stays explicit. + "simpleStorageNativeStoreHitMatchBridge_proved", # Safe-body public EVMYulLean wrapper derives the raw BridgedStmts function # hypotheses from compile output, static parameter closure, and # BridgedSafeStmts witnesses before delegating to the function-bridge @@ -369,6 +364,8 @@ # applying the Yul backend equivalence. The proof is linear hypothesis # plumbing around one public transition theorem. "interpretYulFromIR_evmYulLean_eq_on_bridged_bodies", + "layers2_3_ir_matches_yul_evmYulLeanFuelWrapperDefaultFuel", + "layers2_3_ir_matches_yul_evmYulLeanBackend", # --- Contract proofs (Contracts/) --- "constructor_increment_getCount", "add_one_preserves_order_iff_no_overflow", @@ -401,11 +398,11 @@ # Pure-context dispatch is the same 25-builtin case split specialized to # context-free builtins; each branch delegates to an individual bridge. "evalBuiltinCallWithBackendContext_evmYulLean_pure_bridge", - # Backend-parameterized mirror of execYulFuel; long by construction because + # Backend-parameterized mirror of legacyExecYulFuel; long by construction because # it preserves all statement cases while swapping only expression backend. "execYulFuelWithBackend", # Recovery proof mirrors the executor's statement case split; each branch is - # direct simplification back to execYulFuel. + # direct simplification back to legacyExecYulFuel. "execYulFuelWithBackend_verity_eq", # Native harness block-append lemmas are structural inductions over a Yul # block prefix with fuel normalization at each cons. The success, suffix @@ -460,7 +457,22 @@ # Conditional Layer-3 EVMYulLean theorem composes existing codegen # preservation with emitted-runtime backend equality; the scanner also # counts the trailing Phase 4 summary block in its theorem span. - "yulCodegen_preserves_semantics_evmYulLean", + "yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle", + # Native signed division bridge mirrors the upstream signed arithmetic + # spec split across sign/zero/divisor cases. The proof is a linear case + # analysis over integer-range facts rather than reusable computation. + "int256_div_toUint256_val_eq_uint256_sdiv", + # Native signextend bridge follows EVM's byte-index split and signed-mask + # arithmetic cases. Decomposing would mostly create single-use arithmetic + # helper lemmas with the same hypotheses. + "uint256_signextend_val_eq_uint256_signextend", + # Projected native dispatcher result wrapper has a short proof body, but + # the scanner includes the following public runtime-harness doc block. + "nativeDispatcherExecMatchesIRPositive_of_project_eq_match", + # Private transition wrapper retained only in EvmYulLeanRetarget; the proof + # is a thin composition but its statement carries the full bridged-body + # hypotheses for the isolated legacy regression boundary. + "interpretYulFromIR_evmYulLean_eq_on_bridged_bodies", # Scalar parameter body closure is a structural induction over the six # scalar ABI cases emitted by `genParamLoadBodyFrom`. "genParamLoadBodyFrom_calldataload_bridged", @@ -473,8 +485,11 @@ # has to cover both inline static loads and the generated first-element alias. "genParamLoadBodyFrom_calldataload_static_scalar_bridged", # Source-expression closure main theorem: structural induction over the - # 21 `BridgedSourceExpr` constructors (4 leaves + 17 binops); each binop - # case is 4-5 lines and cannot be merged without losing readability. + # 48 `BridgedSourceExpr` constructors (4 scalar leaves, 36 direct builtin, + # boolean-normalization, bridged environment-read, or unary read cases, and + # 8 branchless helper cases); each case is mechanical decomposition of the + # emitted `compileExpr` shape and cannot be merged without losing + # readability. "compileExpr_bridgedSource", # Pure binding list closure mirrors `compileStmtList`'s head/tail recursion; # most proof lines are boilerplate decomposition of the two Except binds. @@ -657,10 +672,10 @@ # Same recursive generated-shape proof as the external version, using the # internal body fragment so internal returns compile to assignment + leave. "compileStmt_internal_recursive_body_fragment_bridged", - # Require failure-condition source closure case-splits on the 23 + # Require failure-condition source closure case-splits on the 48 # `BridgedSourceExpr` constructors: `.ge`/`.le` are handled specially # because `compileRequireFailCond` uses the direct `lt`/`gt` optimization, - # and the remaining 21 constructors each invoke the shared + # and the remaining 46 constructors each invoke the shared # `compileRequireFailCond_default_bridgedSource` helper for the `iszero` # fall-through. Each constructor case is two mechanical lines; merging # them would require either introducing a generic reconstruction tactic @@ -1024,13 +1039,13 @@ # closure theorem; splitting would create a parallel dispatch helper with # the same 24-case shape. "compileStmtList_always_bridged", + # Universal no-function-definition aggregation mirrors + # compileStmtList_always_bridged: one constructor dispatch over + # BridgedSafeStmts, with each branch delegating to a fragment-specific + # noFuncDefs theorem. + "compileStmtList_always_noFuncDefs", # --- Misc --- "findUniqueInternalFunction", - # Native dispatcher bridge wrapper: mostly argument plumbing through the - # generic Layer 2+3 native theorem after the concrete SimpleStorage lowering - # witness is packaged; splitting would just duplicate the same fixture - # witnesses. - "simpleStorage_endToEnd_native_evmYulLean_of_callDispatcher_bridge", # Native generated-switch block append/error lemmas mirror the existing # ok-append proof and keep the fuel arithmetic visible in one place for # the halt-before-default dispatcher cases. @@ -1042,6 +1057,72 @@ "exec_nativeSwitchCaseIfs_prefix_hit_error_fuel", } +# PR #1822 native EVMYulLean generic-dispatcher closure. These regexes cover +# generated-runtime/native-dispatcher simulation families whose proof spans are +# long because they compose selector dispatch, switch lowering, fuel +# normalization, environment validation, and projected storage/result equality. +# Factoring each endpoint further would mostly create single-use wrappers over +# the same generated dispatcher case split. +ALLOWLIST_REGEXES: tuple[re.Pattern[str], ...] = tuple( + re.compile(pattern) + for pattern in ( + r"^compile_preserves_native_evmYulLean_", + r"^nativeDispatcherExecMatchesIRPositive_of_buildSwitch_", + r"^nativeGenerated(?:SelectorHit|CallDispatcherResult|CallDispatcherMatchesIR)_", + r"^nativeGeneratedSelectorHit(?:SuccessUserBody)?LoweredArtifacts.*$", + r"^NativeGenerated(?:SelectorHit|SelectedUserBody).*", + r"^contractDispatcherExecResult_buildSwitch_noFallback_noReceive_", + r"^contractDispatcherExecResult_block_lowerNativeSwitchBlock_", + r"^exec_(?:block_)?lowerNativeSwitchBlock_.*" + r"(?:generated_prefix|finalMatched_store_fuel)$", + r"^exec_switchCaseBody_nonpayable_prefix_eq$", + r"^exec_if_lt_calldatasize_skip_markedPrefix_ge_fuel$", + r"^NativePrimCallPreservesWord_" + r"(?:log[0-4]|binary_same_state|ternary_same_state|" + r"of_allowed_lookupRuntimePrimOp|[st]store)_values$", + r"^NativePrimCallPreservesWord_of_allowed_lookupRuntimePrimOp$", + r"^Native(?:Stmt|Expr)PreservesWord_.*" + r"(?:mappingContract|nativePreservableStraightStmt|" + r"lowerStmtGroupNativeWithSwitchIds_expr_|" + r"lowerStmtsNativeWithSwitchIds_of_nativePreservableStraightStmts)", + r"^Native(?:MappingFreePreservableStraightStmt|PreservableStraightStmt)" + r"\.of_bridgedStraightStmt$", + r"^NativeStmtPreservesWord_(?:lowerStmtGroupNativeWithSwitchIds|" + r"of_mem_lowerStmtsNativeWithSwitchIds)_of_mappingFreePreservableStraightStmt", + r"^NativeStmtPreservesWord_let(?:Many)?_lowerExprNative_of_mappingFreeBridgedExpr$", + r"^NativeBlockPreservesWord_switchCaseBody_" + r"(?:payable|nonpayable)_of_user_body$", + r"^native_(?:mappingSlot_call_preserves_lookup|" + r"mappingSlot_call_preserves_lookup_state|" + r"call_preserves_lookup_of_revivable_body)$", + r"^nativeGeneratedSelectorHitBodyPreservesMatched_.*$", + r"^nativeGeneratedSelectorHit_success_of_user_body_exec_bridge_atFuel_revived.*$", + r"^nativeResultsMatchOn_execIRFunction_.*_markedPrefix$", + r"^nativeMappingSlotFunctionDefinition_exec_revivable$", + r"^execIRFunction_(?:zeroParam|oneParam|mstore0)_.*$", + r"^projectResult_literalReturnHit_eq$", + r"^exec_block_(?:store0_calldataload4_stop|simpleStorageLoweredStoreCaseBodyTail2)" + r"_markedPrefix_halt$", + r"^exec_switchCaseBody_nonpayable_calldata_revert_fuel$", + r"^exec_if_lowerExprNative_lt_calldatasize_take_lt_revert_fuel$", + r"^lowerStmtGroupNativeWithSwitchIds_ok_of_yulStmtContainsFuncDef_false$", + r"^lowerStmtsNativeWithSwitchIds_switchCaseBody_payable_revert_eq$", + r"^lowerRuntimeContractNative_of_compile_ok_supported_exists$", + r"^lowerStmtsNative(?:WithSwitchIds)?_buildSwitch_noFallback_noReceive_ok_block$", + r"^lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_eq$", + r"^lowerStmtsNativeWithSwitchIds_switchCaseBody_nonpayable_revert_eq$", + r"^sizeOf_(?:buildSwitch_noFallback_noReceive_ge_source_cases_length" + r"(?:_plus24)?|emitYul_runtimeCode_mapping_ge_lowered_cases_length" + r"(?:_plus24)?)$", + r"^supportedStmtList_safe_of_state_" + r"(?:effect_closed|except_mapping_writes_stmt_safety)$", + r"^simpleStorage_source_endToEnd_native_evmYulLean_of_sourceIR$", + r"^compileStmt_setStructMember2_singleSlot_nonzero_bridged$", + r"^compileStmtList_append_eq$", + r"^compile_ok_yields_noReceiveEntrypoint_except_mapping_writes$", + ) +) + # Directories containing proof files to scan. PROOF_DIRS = [ ROOT / "Compiler" / "Proofs", @@ -1088,6 +1169,10 @@ def measure_proofs(lean_file: Path) -> list[tuple[str, int, int]]: return results +def is_allowlisted(name: str) -> bool: + return name in ALLOWLIST or any(pattern.match(name) for pattern in ALLOWLIST_REGEXES) + + def main() -> None: parser = argparse.ArgumentParser(description="Check proof lengths.") parser.add_argument( @@ -1113,7 +1198,7 @@ def main() -> None: for file, name, line, length in all_proofs: if length > HARD_LIMIT: - if name in ALLOWLIST: + if is_allowlisted(name): allowlisted.append((file, name, line, length)) else: violations.append((file, name, line, length)) diff --git a/scripts/check_solc_pin.py b/scripts/check_solc_pin.py index b4e47a203..5b9af0f9e 100644 --- a/scripts/check_solc_pin.py +++ b/scripts/check_solc_pin.py @@ -27,6 +27,7 @@ URL_VERSION_RE = re.compile(r"solc-linux-amd64-v(\d+\.\d+\.\d+)\+commit\.([0-9a-fA-F]{8})$") FOUNDRY_SOLC_RE = re.compile(r'^\s*solc_version\s*=\s*"([^"]+)"\s*$', re.MULTILINE) TRUST_PIN_RE = re.compile(r"\*\*Version\*\*:\s*([0-9]+\.[0-9]+\.[0-9]+\+commit\.[0-9a-fA-F]{8})\s+\(pinned\)") +SOLC_DOWNLOAD_RE = re.compile(r"curl\b[^\n]*\s\"\$SOLC_URL\"\s+-o\s+solc") def _read(path: Path) -> str: @@ -106,10 +107,14 @@ def main() -> int: "TRUST_ASSUMPTIONS.md: pinned solc version must match verify.yml SOLC_VERSION/SOLC_URL" ) - if 'curl -sSfL "$SOLC_URL" -o solc' not in action_text: + if SOLC_DOWNLOAD_RE.search(action_text) is None: errors.append(".github/actions/setup-solc/action.yml: install step must download from $SOLC_URL") if 'echo "${SOLC_SHA256} solc" | sha256sum -c -' not in action_text: errors.append(".github/actions/setup-solc/action.yml: install step must verify $SOLC_SHA256") + if "/usr/local/bin/solc" in action_text: + errors.append(".github/actions/setup-solc/action.yml: solc cache/install path must be workspace-local") + if re.search(r"\bsudo\b", action_text): + errors.append(".github/actions/setup-solc/action.yml: solc install step must not require sudo") if errors: print("solc pin check failed:", file=sys.stderr) diff --git a/scripts/check_yul.py b/scripts/check_yul.py index e72741211..56ded506d 100644 --- a/scripts/check_yul.py +++ b/scripts/check_yul.py @@ -27,14 +27,21 @@ r"^\s*import\s+Compiler\.Proofs\.YulGeneration\.ReferenceOracle\.Builtins\s*$", re.MULTILINE, ) +IMPORT_NATIVE_BUILTINS_RE = re.compile( + r"^\s*import\s+Compiler\.Proofs\.YulGeneration\.Backends\.EvmYulLeanBuiltinSemantics\s*$", + re.MULTILINE, +) BUILTIN_CALL_RE = re.compile( r"\bCompiler\.Proofs\.YulGeneration\.(?:" r"evalBuiltinCall" - r"|evalBuiltinCallWithContext" + r"|legacyEvalBuiltinCallWithContext" r"|evalBuiltinCallWithBackend" r"|evalBuiltinCallWithBackendContext" r")\b" ) +NATIVE_BUILTIN_CALL_RE = re.compile( + r"\bCompiler\.Proofs\.YulGeneration\.Backends\.evalBuiltinCallWithEvmYulLeanContext\b" +) INLINE_DISPATCH_RE = re.compile( r'func\s*=\s*"(?:mappingSlot|sload|add|sub|mul|div|mod|lt|gt|eq|iszero|and|or|xor|not|shl|shr|caller|calldataload|address|timestamp|number)"' ) @@ -200,15 +207,30 @@ def collect_builtin_boundary_failures() -> list[str]: text = scrub_lean_code(lean_file.read_text(encoding="utf-8")) rel = lean_file.relative_to(ROOT) - if not IMPORT_BUILTINS_RE.search(text): - failures.append(f"{rel}: missing import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins") + if lean_file.name == "IRInterpreter.lean": + if not IMPORT_NATIVE_BUILTINS_RE.search(text): + failures.append( + f"{rel}: missing import " + "Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBuiltinSemantics" + ) - if not BUILTIN_CALL_RE.search(text): - failures.append( - f"{rel}: missing call to Compiler.Proofs.YulGeneration." - "evalBuiltinCall, evalBuiltinCallWithContext, " - "evalBuiltinCallWithBackend, or evalBuiltinCallWithBackendContext" - ) + if not NATIVE_BUILTIN_CALL_RE.search(text): + failures.append( + f"{rel}: missing call to Compiler.Proofs.YulGeneration.Backends." + "evalBuiltinCallWithEvmYulLeanContext" + ) + else: + if not IMPORT_BUILTINS_RE.search(text): + failures.append( + f"{rel}: missing import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins" + ) + + if not BUILTIN_CALL_RE.search(text): + failures.append( + f"{rel}: missing call to Compiler.Proofs.YulGeneration." + "evalBuiltinCall, legacyEvalBuiltinCallWithContext, " + "evalBuiltinCallWithBackend, or evalBuiltinCallWithBackendContext" + ) if INLINE_DISPATCH_RE.search(text): failures.append( diff --git a/scripts/evmyullean_capability.py b/scripts/evmyullean_capability.py index 2ebfd9ee2..a9b5fc932 100644 --- a/scripts/evmyullean_capability.py +++ b/scripts/evmyullean_capability.py @@ -18,6 +18,9 @@ LET_BINDING_RE = re.compile( r"^\s*let\s+([A-Za-z_][A-Za-z0-9_']*)(?:\s*:\s*[^:=]+)?\s*:=\s*(.+?)\s*$" ) +DISPATCH_DEF_RE = re.compile( + r"^\s*(?:private\s+)?def\s+(legacyEvalBuiltinCallWithContext|evalBuiltinCall)\b" +) def _strip_outer_parens(text: str) -> str: @@ -123,7 +126,7 @@ def extract_found_builtins_with_diagnostics( line = _strip_lean_line_comment(raw_line) if not in_eval_builtin: - if line.lstrip().startswith("def evalBuiltinCall"): + if DISPATCH_DEF_RE.match(line): in_eval_builtin = True eval_indent = len(line) - len(line.lstrip()) continue diff --git a/scripts/generate_evmyullean_adapter_report.py b/scripts/generate_evmyullean_adapter_report.py index 34f5f9e7c..e5068039e 100644 --- a/scripts/generate_evmyullean_adapter_report.py +++ b/scripts/generate_evmyullean_adapter_report.py @@ -20,6 +20,7 @@ ROOT / "Compiler" / "Proofs" / "YulGeneration" / "Backends" ) ADAPTER_FILE = BACKENDS_DIR / "EvmYulLeanAdapter.lean" +BRIDGE_PREDICATES_FILE = BACKENDS_DIR / "EvmYulLeanBridgePredicates.lean" BRIDGE_LEMMAS_FILE = BACKENDS_DIR / "EvmYulLeanBridgeLemmas.lean" BRIDGE_TEST_FILE = BACKENDS_DIR / "EvmYulLeanBridgeTest.lean" CORRECTNESS_FILE = BACKENDS_DIR / "EvmYulLeanAdapterCorrectness.lean" @@ -455,13 +456,13 @@ def _parse_context_bridge_lemmas() -> tuple[list[str], list[str]]: def _parse_bridged_builtins_defs() -> tuple[list[str], list[str]]: - """Extract bridgedBuiltins and unbridgedBuiltins from BridgeLemmas file. + """Extract bridgedBuiltins and unbridgedBuiltins from the predicate module. Returns (bridged, unbridged) or empty lists if definitions not found. """ - if not BRIDGE_LEMMAS_FILE.exists(): + if not BRIDGE_PREDICATES_FILE.exists(): return [], [] - text = BRIDGE_LEMMAS_FILE.read_text(encoding="utf-8") + text = BRIDGE_PREDICATES_FILE.read_text(encoding="utf-8") code = _strip_lean_comments(text) def _extract_string_list(pattern: re.Pattern[str]) -> list[str]: @@ -590,6 +591,13 @@ def _has_theorem_in(code: str, name: str) -> bool: ) return re.search(pattern, code, re.MULTILINE) is not None + def _has_private_theorem_in(code: str, name: str) -> bool: + pattern = ( + r'^[ \t]{0,2}(?:@\[[^\]]*\]\s*)*' + r'private\s+theorem\s+' + re.escape(name) + r'\b' + ) + return re.search(pattern, code, re.MULTILINE) is not None + def _has_theorem(name: str) -> bool: return _has_theorem_in(retarget_code, name) @@ -656,20 +664,23 @@ def _theorem_body_has_sorry(name: str) -> bool: "emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies" ) has_layer3_evm_retarget = _has_theorem( - "yulCodegen_preserves_semantics_evmYulLean" + "yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle" ) if END_TO_END_FILE.exists(): end_to_end_code = _strip_lean_strings( _strip_lean_comments(END_TO_END_FILE.read_text(encoding="utf-8")) ) has_end_to_end_evm_retarget = _has_theorem_in( - end_to_end_code, "layers2_3_ir_matches_yul_evmYulLean" + end_to_end_code, "layers2_3_ir_matches_yul_evmYulLeanBackend" + ) + end_to_end_evm_retarget_is_private = _has_private_theorem_in( + end_to_end_code, "layers2_3_ir_matches_yul_evmYulLeanBackend" ) end_to_end_evm_retarget_has_sorry = _theorem_body_has_sorry_in( - end_to_end_code, "layers2_3_ir_matches_yul_evmYulLean" + end_to_end_code, "layers2_3_ir_matches_yul_evmYulLeanBackend" ) end_to_end_evm_retarget_block = _theorem_block_in( - end_to_end_code, "layers2_3_ir_matches_yul_evmYulLean" + end_to_end_code, "layers2_3_ir_matches_yul_evmYulLeanBackend" ) end_to_end_evm_retarget_has_body_hypotheses = bool( re.search( @@ -680,6 +691,7 @@ def _theorem_body_has_sorry(name: str) -> bool: ) else: has_end_to_end_evm_retarget = False + end_to_end_evm_retarget_is_private = False end_to_end_evm_retarget_has_sorry = False end_to_end_evm_retarget_has_body_hypotheses = False backends_agree_has_sorry = _theorem_body_has_sorry("backends_agree_on_bridged_builtins") @@ -707,7 +719,7 @@ def _theorem_body_has_sorry(name: str) -> bool: "emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies" ) layer3_evm_retarget_has_sorry = _theorem_body_has_sorry( - "yulCodegen_preserves_semantics_evmYulLean" + "yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle" ) admitted_deps = sorted(admitted_lemmas) admitted_dep_status = ( @@ -802,7 +814,10 @@ def _theorem_body_has_sorry(name: str) -> bool: else: layer3_evm_retarget_status = "proven (conditional on bridged IR bodies)" if not has_end_to_end_evm_retarget: - end_to_end_evm_retarget_status = "missing" + end_to_end_evm_retarget_status = ( + "removed from EndToEnd surface " + "(retarget evidence isolated in EvmYulLeanRetarget.lean)" + ) elif end_to_end_evm_retarget_has_sorry: end_to_end_evm_retarget_status = "sorry" elif admitted_deps: @@ -811,6 +826,10 @@ def _theorem_body_has_sorry(name: str) -> bool: end_to_end_evm_retarget_status = ( "proven (conditional on bridged IR bodies)" ) + elif end_to_end_evm_retarget_is_private: + end_to_end_evm_retarget_status = ( + "private transition lemma (body hypotheses discharged)" + ) else: end_to_end_evm_retarget_status = "proven (body hypotheses discharged)" if BODY_CLOSURE_FILE.exists(): @@ -923,8 +942,8 @@ def _theorem_body_has_sorry(name: str) -> bool: # proven, every compileStmtList output for external-safe source # statement lists discharges `BridgedStmts` without per-call # hypotheses. The phase4 status only reaches - # "full_semantic_integration" after the public EndToEnd theorem - # stops carrying explicit BridgedStmts body hypotheses as well. + # "full_semantic_integration" only after the exported EndToEnd + # theorem stops carrying explicit BridgedStmts body hypotheses. has_universal_body_closure = _has_theorem_in( body_closure_code, "compileStmtList_always_bridged" ) @@ -984,11 +1003,19 @@ def _theorem_body_has_sorry(name: str) -> bool: source_expr_pure_closure_has_sorry = _theorem_body_has_sorry_in( source_expr_closure_code, "compileExpr_bridgedSource" ) + has_source_expr_mapping_chain_closure = _has_theorem_in( + source_expr_closure_code, "compileExpr_mappingChain_bridgedSource" + ) + source_expr_mapping_chain_closure_has_sorry = _theorem_body_has_sorry_in( + source_expr_closure_code, "compileExpr_mappingChain_bridgedSource" + ) else: has_source_expr_leaf_closure = False source_expr_leaf_closure_has_sorry = False has_source_expr_pure_closure = False source_expr_pure_closure_has_sorry = False + has_source_expr_mapping_chain_closure = False + source_expr_mapping_chain_closure_has_sorry = False if not has_scalar_param_body_closure: scalar_param_body_closure_status = "missing" elif scalar_param_body_closure_has_sorry: @@ -1116,7 +1143,24 @@ def _theorem_body_has_sorry(name: str) -> bool: elif source_expr_pure_closure_has_sorry: source_expr_pure_closure_status = "sorry" else: - source_expr_pure_closure_status = "proven (pure source-expression fragment)" + source_expr_pure_closure_status = ( + "proven (source-expression fragment with parameter length, " + "storage, and storage-array length reads, ADT tag/field reads, " + "singleton and nested mapping reads through the abstract " + "mappingSlot bridge, mapping struct-member reads, " + "reserved exponentiation, boolean normalization, branchless " + "helpers, bridged environment reads, and unary calldata/memory/" + "transient reads)" + ) + if not has_source_expr_mapping_chain_closure: + source_expr_mapping_chain_closure_status = "missing" + elif source_expr_mapping_chain_closure_has_sorry: + source_expr_mapping_chain_closure_status = "sorry" + else: + source_expr_mapping_chain_closure_status = ( + "proven (mappingChain source-expression wrapper through " + "the abstract mappingSlot bridge)" + ) if not has_universal_body_closure: universal_body_closure_status = "missing" elif universal_body_closure_has_sorry: @@ -1131,6 +1175,7 @@ def _theorem_body_has_sorry(name: str) -> bool: has_universal_body_closure and not universal_body_closure_has_sorry and has_end_to_end_evm_retarget + and not end_to_end_evm_retarget_is_private and not end_to_end_evm_retarget_has_sorry and not end_to_end_evm_retarget_has_body_hypotheses and has_layer3_evm_retarget @@ -1166,10 +1211,6 @@ def _theorem_body_has_sorry(name: str) -> bool: elif ( has_universal_body_closure and not universal_body_closure_has_sorry - and has_end_to_end_evm_retarget - and not end_to_end_evm_retarget_has_sorry - and has_layer3_evm_retarget - and not layer3_evm_retarget_has_sorry and has_runtime_backend_eq and not runtime_backend_eq_has_sorry and has_runtime_closure @@ -1401,9 +1442,9 @@ def _theorem_body_has_sorry(name: str) -> bool: "identifier-slot sstore), and recursively nested BridgedStmt targets; " "generated runtime-code closure, emitted-runtime backend equality, and the " "lower-level Layer-3 EVMYulLean retarget theorem are proven under bridged " - "IR-body witnesses; the public EndToEnd safe-body wrapper discharges raw " - "BridgedStmts body hypotheses from SupportedSpec, static-parameter, and " - "BridgedSafeStmts source witnesses; " + "IR-body witnesses; the EndToEnd safe-body backend-wrapper lemma is private " + "transition plumbing, while public EndToEnd targets use native dispatcher " + "execution through interpretIRRuntimeNative; " "compileStmtList_always_bridged proves a universal BridgedSafeStmts aggregation " "theorem with the external-call family carved out behind explicit function-table " "hypotheses" @@ -1423,8 +1464,8 @@ def _theorem_body_has_sorry(name: str) -> bool: "execYulFuelWithBackend_eq_on_bridged_target": recursive_target_retarget_status, "emitYul_runtimeCode_bridged": runtime_closure_status, "emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies": runtime_backend_eq_status, - "yulCodegen_preserves_semantics_evmYulLean": layer3_evm_retarget_status, - "layers2_3_ir_matches_yul_evmYulLean": end_to_end_evm_retarget_status, + "yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle": layer3_evm_retarget_status, + "layers2_3_ir_matches_yul_evmYulLeanBackend": end_to_end_evm_retarget_status, "genParamLoads_scalar_bridged": scalar_param_body_closure_status, "genStaticTypeLoads_calldataload_bridged": static_type_body_closure_status, "genParamLoads_static_scalar_bridged": static_param_body_closure_status, @@ -1444,6 +1485,7 @@ def _theorem_body_has_sorry(name: str) -> bool: "compileStmtList_internal_recursive_body_fragment_bridged": internal_recursive_body_fragment_closure_status, "compileExpr_bridgedSource_leaf": source_expr_leaf_closure_status, "compileExpr_bridgedSource": source_expr_pure_closure_status, + "compileExpr_mappingChain_bridgedSource": source_expr_mapping_chain_closure_status, "compileStmtList_always_bridged": universal_body_closure_status, "trust_boundary": phase4_trust_boundary, "remaining_for_whole_program_retargeting": remaining_for_whole_program_retargeting, diff --git a/scripts/prune_lake_cache.py b/scripts/prune_lake_cache.py index 8401ead49..7223a9d8f 100644 --- a/scripts/prune_lake_cache.py +++ b/scripts/prune_lake_cache.py @@ -8,6 +8,7 @@ import subprocess import sys from pathlib import Path +import argparse ROOT = Path(__file__).resolve().parents[1] @@ -47,7 +48,15 @@ def remove_path(path: Path, reason: str) -> None: shutil.rmtree(path) -def main() -> int: +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser() + parser.add_argument( + "--packages-only", + action="store_true", + help="prune stale package checkouts without clearing .lake/build outputs", + ) + args = parser.parse_args([] if argv is None else argv) + package_dirs: list[Path] = [] if PACKAGES_DIR.exists(): package_dirs = [path for path in PACKAGES_DIR.iterdir() if path.is_dir()] @@ -69,6 +78,9 @@ def main() -> int: if actual_rev != expected_rev: remove_path(package_dir, f"expected {expected_rev[:12]}, found {actual_rev[:12]}") + if args.packages_only: + return 0 + root_build = LAKE_DIR / "build" if root_build.exists(): remove_path(root_build, "clearing root build outputs after partial cache restore") @@ -83,4 +95,4 @@ def main() -> int: if __name__ == "__main__": - sys.exit(main()) + sys.exit(main(sys.argv[1:])) diff --git a/scripts/test_check_native_transition_doc.py b/scripts/test_check_native_transition_doc.py index f11cfe80f..dc388044b 100644 --- a/scripts/test_check_native_transition_doc.py +++ b/scripts/test_check_native_transition_doc.py @@ -2,7 +2,6 @@ from __future__ import annotations -import re import unittest from pathlib import Path import sys @@ -13,10 +12,50 @@ class NativeTransitionDocCheckTests(unittest.TestCase): + def replace_in_theorem_signature( + self, text: str, theorem_name: str, old: str, new: str + ) -> str: + signature = check.theorem_signature(text, theorem_name) + self.assertIn(old, signature) + start = text.index(signature) + return text[:start] + signature.replace(old, new, 1) + text[start + len(signature) :] + def test_current_doc_passes(self) -> None: text = check.DOC.read_text(encoding="utf-8") self.assertEqual(check.check_doc(text), []) + def test_current_definition_of_done_doc_passes(self) -> None: + text = check.DOD_DOC.read_text(encoding="utf-8") + self.assertEqual(check.check_definition_of_done_doc(text), []) + + def test_current_yul_generation_readme_passes(self) -> None: + text = check.YULGEN_README.read_text(encoding="utf-8") + self.assertEqual(check.check_yul_generation_readme(text), []) + + def test_yul_generation_readme_rejects_legacy_main_preservation_status(self) -> None: + text = check.YULGEN_README.read_text(encoding="utf-8").replace( + "**`Preservation.lean`** - Legacy Layer 3 preservation theorem", + "**`Preservation.lean`** - Main Layer 3 preservation theorem", + 1, + ) + errors = check.check_yul_generation_readme(text) + self.assertTrue( + any("Main Layer 3 preservation theorem" in error for error in errors), + errors, + ) + + def test_definition_of_done_doc_rejects_removed_fuel_wrapper_target(self) -> None: + text = check.DOD_DOC.read_text(encoding="utf-8").replace( + "interpretYulRuntimeWithBackend .evmYulLean", + "interpretYulRuntimeEvmYulLeanFuelWrapperDefaultFuel", + 1, + ) + errors = check.check_definition_of_done_doc(text) + self.assertTrue( + any("FuelWrapperDefaultFuel" in error for error in errors), + errors, + ) + def test_rejects_missing_blocker_issue(self) -> None: text = check.DOC.read_text(encoding="utf-8").replace("#1738", "#0000") errors = check.check_doc(text) @@ -60,6 +99,201 @@ def test_rejects_authoritative_native_claim(self) -> None: errors = check.check_doc(text) self.assertTrue(any("overstates" in error for error in errors), errors) + def test_rejects_missing_reference_oracle_retarget_caveat(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "`yulCodegen_preserves_semantics_via_reference_oracle`", + "`native_yulCodegen_preserves_semantics`", + ) + errors = check.check_doc(text) + self.assertTrue( + any("yulCodegen_preserves_semantics_via_reference_oracle" in error for error in errors), + errors, + ) + + def test_rejects_missing_explicit_evmyullean_backend_name(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "`yulCodegen_preserves_semantics_evmYulLeanBackend`", + "`yulCodegen_preserves_semantics_evmYulLean`", + ) + errors = check.check_doc(text) + self.assertTrue( + any( + "yulCodegen_preserves_semantics_evmYulLeanBackend" in error + for error in errors + ), + errors, + ) + + def test_rejects_missing_selected_user_body_result_blocker(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel", + "NativeGeneratedSelectedUserBodyHiddenBridgeAtFuel", + ) + errors = check.check_doc(text) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyResultBridgeAtFuel" in error for error in errors), + errors, + ) + + def test_rejects_missing_threshold_only_public_guard_caveat(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "`SupportedSpec` carries the selected function calldata-threshold inventory", + "selected function full guard inventory", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("calldata-threshold" in error for error in errors), + errors, + ) + + def test_rejects_missing_no_mapping_helper_free_preservation_caveat(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "no-mapping helper-free straight-body preservation bridge", + "selected user-body preservation bridge", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("no-mapping helper-free straight-body preservation" in error for error in errors), + errors, + ) + + def test_rejects_missing_mapping_free_preservation_progress_note(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_mappingFreePreservableStraightStmts", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_genericStraightStmts", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("mappingFreePreservableStraightStmts" in error for error in errors), + errors, + ) + + def test_rejects_missing_singleton_leave_exec_only_progress_note(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body", + "NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_hidden_body", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("of_leave_body" in error for error in errors), + errors, + ) + + def test_rejects_missing_singleton_stop_halt_progress_note(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_stop_body", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_hidden_stop_body", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("of_stop_body" in error for error in errors), + errors, + ) + + def test_rejects_missing_singleton_stop_dispatcher_progress_note(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_stop_body", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden_stop_body", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("compile_ok_supported_stop_body" in error for error in errors), + errors, + ) + + def test_rejects_missing_literal_return_dispatcher_progress_note(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_lit_return32", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden_lit_return32", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("mstore0_lit_return32" in error for error in errors), + errors, + ) + + def test_rejects_missing_calldataload_return_dispatcher_progress_note(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload4_return32", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden_calldataload4_return32", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("mstore0_calldataload4_return32" in error for error in errors), + errors, + ) + + def test_rejects_missing_aligned_calldata_return_seam_note(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "execIRFunction_mstore0_calldataload_aligned_return32", + "execIRFunction_mstore0_calldataload_hidden_return32", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("calldataload_aligned_return32" in error for error in errors), + errors, + ) + + def test_rejects_missing_source_level_generated_dispatcher_public_note(self) -> None: + # The doc may mention the canonical theorem name several times (status + # blurb, G1 plan, achievement summary). Replace every occurrence so the + # check actually sees a doc with no mention of the public theorem. + text = check.DOC.read_text(encoding="utf-8").replace( + "compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher", + "compile_preserves_native_evmYulLean_of_compile_ok_supported_hidden_callDispatcher", + ) + errors = check.check_doc(text) + self.assertTrue( + any("compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher" in error + for error in errors), + errors, + ) + + def test_rejects_missing_legacy_compile_preserves_private_surface_note(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "Legacy premise-taking `compile_preserves_native_evmYulLean_*`", + "Legacy premise-taking `compile_preserves_native_evmYulLean_hidden`", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("compile_preserves_native_evmYulLean_*" in error for error in errors), + errors, + ) + + def test_rejects_missing_mapping_free_bridged_straight_adapter_note(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mappingFree", + "NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_hidden", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("bridgedStraightStmts_mappingFree" in error for error in errors), + errors, + ) + + def test_rejects_missing_mapping_free_dispatcher_adapter_note(self) -> None: + text = check.DOC.read_text(encoding="utf-8").replace( + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree", + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_hidden", + 1, + ) + errors = check.check_doc(text) + self.assertTrue( + any("bridgedStraightStmts_mappingFree" in error for error in errors), + errors, + ) + def test_public_theorem_target_guard_accepts_current_transition_shape(self) -> None: errors = check.check_public_theorem_target( check.END_TO_END.read_text(encoding="utf-8"), @@ -68,11 +302,11 @@ def test_public_theorem_target_guard_accepts_current_transition_shape(self) -> N ) self.assertEqual(errors, []) - def test_public_theorem_target_guard_rejects_missing_current_target(self) -> None: - end_to_end_text = re.sub( - r"interpretYulRuntimeWithBackend\s+\.evmYulLean", - "interpretYulRuntimeWithBackend .verity", - check.END_TO_END.read_text(encoding="utf-8"), + def test_public_theorem_target_guard_rejects_missing_call_dispatcher_match_surface(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "def nativeGeneratedCallDispatcherMatchesIROn", + "def nativeGeneratedHiddenCallDispatcherMatchesIROn", + 1, ) errors = check.check_public_theorem_target( end_to_end_text, @@ -80,26 +314,65 @@ def test_public_theorem_target_guard_rejects_missing_current_target(self) -> Non check.RETARGET.read_text(encoding="utf-8"), ) self.assertTrue( - any("interpretYulRuntimeWithBackend .evmYulLean" in error for error in errors), + any("nativeGeneratedCallDispatcherMatchesIROn" in error for error in errors), errors, ) - def test_public_theorem_target_guard_accepts_native_theorem_seam(self) -> None: - end_to_end_text = ( - check.END_TO_END.read_text(encoding="utf-8") - + "\n-- theorem target: interpretIRRuntimeNative\n" + def test_public_theorem_target_guard_rejects_missing_mapping_free_expression_seam(self) -> None: + native_harness_text = check.NATIVE_HARNESS.read_text(encoding="utf-8").replace( + "theorem NativeExprPreservesWord_lowerExprNative_of_mappingFreeBridgedExpr", + "theorem NativeExprPreservesWord_lowerExprNative_of_hiddenMappingFreeBridgedExpr", + 1, + ) + errors = check.check_public_theorem_target( + check.END_TO_END.read_text(encoding="utf-8"), + native_harness_text, + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("mappingFreeBridgedExpr" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_mapping_free_block_seam(self) -> None: + native_harness_text = check.NATIVE_HARNESS.read_text(encoding="utf-8").replace( + "theorem NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_mappingFreePreservableStraightStmts", + "theorem NativeBlockPreservesWord_lowerStmtsNativeWithSwitchIds_of_hiddenMappingFreePreservableStraightStmts", + 1, + ) + errors = check.check_public_theorem_target( + check.END_TO_END.read_text(encoding="utf-8"), + native_harness_text, + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("mappingFreePreservableStraightStmts" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_call_dispatcher_result_surface(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "noncomputable def nativeGeneratedCallDispatcherResultOf", + "noncomputable def nativeGeneratedHiddenCallDispatcherResultOf", + 1, ) errors = check.check_public_theorem_target( end_to_end_text, check.NATIVE_HARNESS.read_text(encoding="utf-8"), check.RETARGET.read_text(encoding="utf-8"), ) - self.assertEqual(errors, []) + self.assertTrue( + any("nativeGeneratedCallDispatcherResultOf" in error for error in errors), + errors, + ) - def test_public_theorem_target_guard_rejects_missing_native_bridge_obligation(self) -> None: + def test_public_theorem_target_guard_rejects_missing_exact_call_dispatcher_theorem(self) -> None: end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( - "nativeIRRuntimeAgreesWithInterpreter", - "nativeRuntimeBridgeObligation", + "\ntheorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported\n" + " (spec : CompilationModel.CompilationModel)", + "\ntheorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden\n" + " (spec : CompilationModel.CompilationModel)", + 1, ) errors = check.check_public_theorem_target( end_to_end_text, @@ -107,65 +380,2653 @@ def test_public_theorem_target_guard_rejects_missing_native_bridge_obligation(se check.RETARGET.read_text(encoding="utf-8"), ) self.assertTrue( - any("nativeIRRuntimeAgreesWithInterpreter" in error for error in errors), + any("nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported" in error for error in errors), errors, ) - def test_public_theorem_target_guard_rejects_low_level_native_target(self) -> None: - end_to_end_text = ( - check.END_TO_END.read_text(encoding="utf-8") - + "\n-- theorem target: EvmYul.Yul.callDispatcher\n" + def test_public_theorem_target_guard_rejects_exact_call_dispatcher_theorem_adapter_target(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported", + "nativeGeneratedCallDispatcherResultOf", + "Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative", ) errors = check.check_public_theorem_target( end_to_end_text, check.NATIVE_HARNESS.read_text(encoding="utf-8"), check.RETARGET.read_text(encoding="utf-8"), ) - self.assertTrue(any("callDispatcher" in error for error in errors), errors) + self.assertTrue( + any("interpretIRRuntimeNative" in error for error in errors), + errors, + ) - def test_public_theorem_target_guard_rejects_missing_fuel_aligned_oracle(self) -> None: - retarget_text = check.RETARGET.read_text(encoding="utf-8").replace( - "interpretYulRuntimeWithBackendFuel", - "interpretYulRuntimeWithBackendDefaultFuel", + def test_public_theorem_target_guard_rejects_exact_call_dispatcher_theorem_without_selected_user_body_halt_bridge(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel", + "NativeGeneratedSelectedUserBodyHiddenHaltExecBridgeAtFuel", ) errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_source_level_generated_theorem_without_source_target(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( check.END_TO_END.read_text(encoding="utf-8"), + "compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher", + "sourceResultMatchesNativeOn", + "nativeResultsMatchOn", + ) + errors = check.check_public_theorem_target( + end_to_end_text, check.NATIVE_HARNESS.read_text(encoding="utf-8"), - retarget_text, + check.RETARGET.read_text(encoding="utf-8"), ) self.assertTrue( - any("interpretYulRuntimeWithBackendFuel" in error for error in errors), + any("sourceResultMatchesNativeOn" in error for error in errors), errors, ) - def test_unbridged_environment_boundary_accepts_current_shape(self) -> None: - errors = check.check_unbridged_environment_boundary( + def test_public_theorem_target_guard_rejects_source_level_generated_theorem_direct_projected_target(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher", + "Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative", + "nativeGeneratedCallDispatcherResultOf", + ) + errors = check.check_public_theorem_target( + end_to_end_text, check.NATIVE_HARNESS.read_text(encoding="utf-8"), - check.NATIVE_SMOKE_TEST.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("nativeGeneratedCallDispatcherResultOf" in error for error in errors), + errors, ) - self.assertEqual(errors, []) - def test_unbridged_environment_boundary_rejects_missing_chainid_rejection_pin(self) -> None: - smoke_text = check.NATIVE_SMOKE_TEST.read_text(encoding="utf-8").replace( - 'nativeRejectsUnsupportedChainId = true', - 'nativeAcceptsUnsupportedChainId = true', + def test_public_theorem_target_guard_rejects_legacy_compile_preserves_public_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical", + "theorem compile_preserves_native_evmYulLean_selector_miss_noMapping_canonical", + 1, ) - errors = check.check_unbridged_environment_boundary( + errors = check.check_public_theorem_target( + end_to_end_text, check.NATIVE_HARNESS.read_text(encoding="utf-8"), - smoke_text, + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("unexpected public theorem" in error for error in errors), + errors, ) - self.assertTrue(any("chainid" in error.lower() for error in errors), errors) - def test_unbridged_environment_boundary_rejects_missing_blobbasefee_rejection_pin(self) -> None: - smoke_text = check.NATIVE_SMOKE_TEST.read_text(encoding="utf-8").replace( - 'nativeRejectsUnsupportedBlobBaseFee = true', - 'nativeAcceptsUnsupportedBlobBaseFee = true', + def test_public_theorem_target_guard_rejects_exact_call_dispatcher_theorem_exposing_dispatch_guards(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported", + "4 + tx.args.length * 32 < EvmYul.UInt256.size", + "DispatchGuardsSafe fn tx", ) - errors = check.check_unbridged_environment_boundary( + errors = check.check_public_theorem_target( + end_to_end_text, check.NATIVE_HARNESS.read_text(encoding="utf-8"), - smoke_text, + check.RETARGET.read_text(encoding="utf-8"), ) - self.assertTrue(any("blobbasefee" in error for error in errors), errors) + self.assertTrue( + any("DispatchGuardsSafe" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_source_threshold_inventory(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported", + "hUserBodyHalt", + "selectorDispatchedFunctions spec", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("selectorDispatchedFunctions spec" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_lowering_witness_name(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported", + "hUserBodyHalt", + "hLowerRuntime", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("hLowerRuntime" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_exact_call_dispatcher_lower_witness(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported", + "nativeResultsMatchOn observableSlots", + "Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative\n" + " (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧\n" + " nativeResultsMatchOn observableSlots", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("lowerRuntimeContractNative" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_source_level_lower_witness(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher", + "sourceResultMatchesNativeOn observableSlots", + "Compiler.Proofs.YulGeneration.Backends.lowerRuntimeContractNative\n" + " (Compiler.emitYul irContract).runtimeCode = .ok nativeContract ∧\n" + " sourceResultMatchesNativeOn observableSlots", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("lowerRuntimeContractNative" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_private_selected_user_body_halt_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "def NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel", + "private def NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "must keep the public exact generated callDispatcher selected user-body halt bridge publicly nameable" + in error + for error in errors + ), + errors, + ) + self.assertTrue( + any( + "must not make the public exact generated callDispatcher selected user-body halt bridge private" + in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_private_success_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "def NativeGeneratedSelectorHitSuccessBridge", + "private def NativeGeneratedSelectorHitSuccessBridge", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "must keep the remaining success-case selector-hit bridge publicly nameable" + in error + for error in errors + ), + errors, + ) + self.assertTrue( + any("must not make the remaining success-case selector-hit bridge private" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_exact_call_dispatcher_theorem_exposing_direct_user_body_bridge(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state\n observableSlots", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state\n observableSlots)\n" + " (hSelectedUserBodyExec :\n" + " NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived irContract tx\n" + " state observableSlots", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_exact_call_dispatcher_theorem_exposing_preservation_bridge(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state\n observableSlots", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state\n observableSlots)\n" + " (hPreserves :\n" + " NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel irContract tx", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_exact_call_dispatcher_theorem_exposing_generated_prefix_continuation(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state\n observableSlots", + "NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel irContract tx state\n observableSlots)\n" + " (hGeneratedPrefixCont :\n" + " NativeGeneratedSelectorHitUserBodyGeneratedPrefixContinuation irContract\n" + " tx state observableSlots", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectorHitUserBodyGeneratedPrefixContinuation" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_exact_call_dispatcher_wrapper_deprecation_target(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "attribute [deprecated nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported\n" + " (since := \"2026-05-07\")]", + "attribute [deprecated nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selector_hit_user_body_exec_bridge_success_only_atFuel_revived_and_continuation\n" + " (since := \"2026-05-07\")]", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("compatibility wrappers must be deprecated" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_exact_wrapper_deprecation(self) -> None: + removed_wrapper = ( + " nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_empty_selected_body\n" + ) + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + removed_wrapper, + "", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("empty_selected_body" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_interpret_wrapper_deprecation_target(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "attribute [deprecated compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match\n" + " (since := \"2026-05-07\")]", + "attribute [deprecated compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match\n" + " (since := \"2026-05-07\")]", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("interpretIRRuntimeNative compatibility wrappers" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_interpret_wrapper_deprecation(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + " compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_environment\n" + " compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_globalDefaults\n", + " compile_preserves_native_evmYulLean_of_interpretIRRuntimeNative_match_mapping_dispatcher_ofIR_environment\n", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("match_mapping_dispatcher_ofIR_globalDefaults" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_interpret_eq_wrapper_deprecation_target(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "attribute [deprecated nativeGeneratedCallDispatcherResultOf\n" + " (since := \"2026-05-07\")]", + "attribute [deprecated nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported\n" + " (since := \"2026-05-07\")]", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("interpretIRRuntimeNative equality wrappers" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_interpret_eq_wrapper_deprecation(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + " nativeGeneratedCallDispatcherResultOf_eq_interpretIRRuntimeNative_of_lowerRuntimeContractNative_supported_except_mapping_writes_stmt_safety\n", + "", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("except_mapping_writes_stmt_safety" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_exec_only_body_bridge_split(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "def NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived", + "def NativeGeneratedSelectorHitUserBodyExecHiddenBridgeAtFuelRevived", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_direct_user_body_exec_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "def NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived", + "def NativeGeneratedSelectedUserBodyExecHiddenBridgeAtFuelRevived", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_direct_user_body_result_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "def NativeGeneratedSelectedUserBodyResultBridgeAtFuel", + "def NativeGeneratedSelectedUserBodyHiddenResultBridgeAtFuel", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyResultBridgeAtFuel" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_preservation_body_bridge_split(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "def NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel", + "def NativeGeneratedSelectorHitUserBodyHiddenPreservesBridgeAtFuel", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_generated_prefix_continuation_split(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "def NativeGeneratedSelectorHitUserBodyGeneratedPrefixContinuation", + "def NativeGeneratedSelectorHitUserBodyHiddenGeneratedPrefixContinuation", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectorHitUserBodyGeneratedPrefixContinuation" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_exec_only_bridge_projection(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_exec_bridge", + "theorem NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_hidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("ExecOnlyBridgeAtFuelRevived.of_exec_bridge" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_direct_user_body_exec_projection(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_selected_user_body_exec_only", + "theorem NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived.of_selected_user_body_hidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("of_selected_user_body_exec_only" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_preservation_bridge_projection(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_exec_bridge", + "theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_hidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("PreservesBridgeAtFuel.of_exec_bridge" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_preservation_bridge_constructor(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_forall_stmt_write_not_mem", + "theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_hidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("of_forall_stmt_write_not_mem" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_block_fresh_preservation_bridge_constructor(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_nativeStmtsWriteNames_not_mem", + "theorem NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_nativeStmtsWriteNames_hidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("of_nativeStmtsWriteNames_not_mem" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_body_bridge_recombiner(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_and_preserves", + "theorem NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_hidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("of_exec_only_and_preserves" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_result_bridge_constructor(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_preserves", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_hidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("ResultBridgeAtFuel.of_exec_only_and_preserves" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_block_fresh_result_bridge_constructor(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_nativeStmtsWriteNames_not_mem", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_nativeStmtsWriteNames_hidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "ResultBridgeAtFuel.of_exec_only_and_nativeStmtsWriteNames_not_mem" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_mapping_straight_result_bridge_constructor(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mapping", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_hidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "ResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mapping" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_mapping_free_straight_result_bridge_constructor(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mappingFree", + "private theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_noMappingHidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "ResultBridgeAtFuel.of_exec_only_and_bridgedStraightStmts_mappingFree" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_mapping_free_dispatcher_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree", + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_with_selected_user_body_exec_only_and_bridgedStraightStmts_noMappingHidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "with_selected_user_body_exec_only_and_bridgedStraightStmts_mappingFree" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_selector_miss_exists_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_exists_of_compile_ok_supported", + "theorem nativeGeneratedCallDispatcherResult_selector_miss_matchesIR_hidden_of_compile_ok_supported", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("selector_miss_matchesIR_exists_of_compile_ok_supported" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_nonpayable_guard_exists_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_exists_of_compile_ok_supported", + "theorem nativeGeneratedCallDispatcherResult_selector_hit_nonpayable_nonzero_revert_matchesIR_hidden_of_compile_ok_supported", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "selector_hit_nonpayable_nonzero_revert_matchesIR_exists_of_compile_ok_supported" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_args_short_guard_exists_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_exists_of_compile_ok_supported", + "theorem nativeGeneratedCallDispatcherResult_selector_hit_args_short_revert_matchesIR_hidden_of_compile_ok_supported", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "selector_hit_args_short_revert_matchesIR_exists_of_compile_ok_supported" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_hit_error_exists_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem nativeGeneratedCallDispatcherResult_selector_hit_error_matchesIR_exists_of_compile_ok_supported", + "theorem nativeGeneratedCallDispatcherResult_selector_hit_error_matchesIR_hidden_of_compile_ok_supported", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("selector_hit_error_matchesIR_exists_of_compile_ok_supported" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_lower_runtime_exists_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem lowerRuntimeContractNative_of_compile_ok_supported_exists", + "theorem lowerRuntimeContractNative_of_compile_ok_supported_hidden", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("lowerRuntimeContractNative_of_compile_ok_supported_exists" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_selected_body_lowering_handoff(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem selectedFunctionBodyBridgedAndLowered_of_compile_ok_supported", + "theorem selectedFunctionBodyBridgedAndLowered_hidden_of_compile_ok_supported", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("selectedFunctionBodyBridgedAndLowered_of_compile_ok_supported" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_success_user_body_artifact_exists_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_exists_of_compile_ok_supported", + "theorem nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_hidden_of_compile_ok_supported", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "nativeGeneratedSelectorHitSuccessUserBodyLoweredArtifacts_exists_of_compile_ok_supported" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_leave_exec_only_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body", + "theorem NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_hidden_body", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_stop_halt_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_stop_body", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_hidden_stop_body", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_stop_body" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_stop_result_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_stop_body", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_hidden_stop_body", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_stop_body" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_stop_dispatcher_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_stop_body", + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden_stop_body", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("compile_ok_supported_stop_body" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_literal_return_halt_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_lit_return32", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_hidden_lit_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_lit_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_literal_return_result_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_lit_return32", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_hidden_lit_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_lit_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_literal_return_dispatcher_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_lit_return32", + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden_lit_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("compile_ok_supported_mstore0_lit_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_zero_param_literal_return_halt_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_lit_return32", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_hidden_zeroParam_lit_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_lit_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_zero_param_literal_return_result_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_lit_return32", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_hidden_zeroParam_lit_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_lit_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_zero_param_literal_return_dispatcher_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_lit_return32", + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden_zeroParam_lit_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("compile_ok_supported_zeroParam_mstore0_lit_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_zero_param_literal_return_source_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_lit_return32", + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden_source_zeroParam_lit_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("compile_ok_supported_source_zeroParam_lit_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_zero_param_sload_return_halt_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_sload0_return32", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_hidden_zeroParam_sload0_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_zeroParam_mstore0_sload0_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_zero_param_sload_return_result_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_sload0_return32", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_hidden_zeroParam_sload0_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_zeroParam_mstore0_sload0_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_zero_param_sload_return_dispatcher_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_zeroParam_mstore0_sload0_return32", + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden_zeroParam_sload0_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("compile_ok_supported_zeroParam_mstore0_sload0_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_zero_param_sload_return_source_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_source_zeroParam_sload0_return32", + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden_source_zeroParam_sload0_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("compile_ok_supported_source_zeroParam_sload0_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_calldataload_return_halt_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload4_return32", + "theorem NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_hidden_calldataload4_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyHaltExecBridgeAtFuel.of_mstore0_calldataload4_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_calldataload_return_result_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload4_return32", + "theorem NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_hidden_calldataload4_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("NativeGeneratedSelectedUserBodyResultBridgeAtFuel.of_mstore0_calldataload4_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_calldataload_return_dispatcher_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_mstore0_calldataload4_return32", + "private theorem nativeGeneratedCallDispatcherMatchesIR_of_compile_ok_supported_hidden_calldataload4_return32", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("compile_ok_supported_mstore0_calldataload4_return32" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_unsafe_leave_preservation_bridge(self) -> None: + native_harness_text = ( + check.NATIVE_HARNESS.read_text(encoding="utf-8") + + "\ntheorem NativeStmtPreservesWord_leave : True := by trivial\n" + ) + errors = check.check_public_theorem_target( + check.END_TO_END.read_text(encoding="utf-8"), + native_harness_text, + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "must not close the selected-body result bridge" in error + and "raw `leave`" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_exec_only_body_bridge_split(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private def NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived", + "def NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "must keep the selected selector-hit bridge seam private" in error + and "NativeGeneratedSelectorHitUserBodyExecOnlyBridgeAtFuelRevived" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_direct_user_body_exec_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private def NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived", + "def NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "must keep the selected selector-hit bridge seam private" in error + and "NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_direct_user_body_result_bridge(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private def NativeGeneratedSelectedUserBodyResultBridgeAtFuel", + "def NativeGeneratedSelectedUserBodyResultBridgeAtFuel", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "must keep the selected selector-hit bridge seam private" in error + and "NativeGeneratedSelectedUserBodyResultBridgeAtFuel" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_body_bridge_recombiner(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_and_preserves", + "theorem NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevived.of_exec_only_and_preserves", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "must keep the selected selector-hit bridge seam private" in error + and "of_exec_only_and_preserves" in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_dispatcher_exec_surface(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + .replace( + "private def nativeGeneratedDispatcherExecMatchesIROn", + "def nativeGeneratedDispatcherExecMatchesIROn", + 1, + ) + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("dispatcher-exec compatibility seams private" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_removed_generated_call_dispatcher_adapter(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\nprivate theorem compile_preserves_native_evmYulLean_of_generated_callDispatcher_match " + + ": True := by trivial\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("removed backend-wrapper transition lemma" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_native_results_adapter(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem compile_preserves_native_evmYulLean_of_nativeResultsMatchOn", + "theorem compile_preserves_native_evmYulLean_of_nativeResultsMatchOn", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("adapter theorem file-local" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_direct_generated_call_dispatcher_theorem(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "theorem compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match", + "theorem compile_preserves_native_evmYulLean_hiddenCallDispatcher_of_generated_callDispatcher_match", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match" + in error + for error in errors + ), + errors, + ) + + def test_public_theorem_target_guard_rejects_missing_lowered_call_dispatcher_wrappers(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8") + end_to_end_text = end_to_end_text.replace( + "theorem compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping", + "theorem compile_preserves_native_evmYulLean_of_lowered_generated_hiddenCallDispatcher_noMapping", + 1, + ).replace( + "theorem compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping", + "theorem compile_preserves_native_evmYulLean_of_lowered_generated_hiddenCallDispatcher_mapping", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("lowered_generated_callDispatcher_noMapping" in error for error in errors), + errors, + ) + self.assertTrue( + any("lowered_generated_callDispatcher_mapping" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_undeprecated_call_dispatcher_wrapper(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "@[deprecated compile_preserves_native_evmYulLean_of_nativeGeneratedCallDispatcherResult_match\n" + " (since := \"2026-05-07\")]\n" + "private theorem compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match", + "theorem compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match", + 1, + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("must be marked deprecated" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_lowered_nomapping_adapter_target(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_noMapping", + "nativeGeneratedCallDispatcherResultOf", + "Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("thin runtime adapter" in error for error in errors), + errors, + ) + self.assertTrue( + any("interpretIRRuntimeNative" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_base_call_dispatcher_adapter_target(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match", + "nativeGeneratedCallDispatcherResultOf", + "Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("thin runtime adapter" in error for error in errors), + errors, + ) + self.assertTrue( + any("interpretIRRuntimeNative" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_lowered_mapping_adapter_target(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "compile_preserves_native_evmYulLean_of_lowered_generated_callDispatcher_mapping", + "nativeGeneratedCallDispatcherResultOf", + "Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("thin runtime adapter" in error for error in errors), + errors, + ) + self.assertTrue( + any("interpretIRRuntimeNative" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_legacy_backend_target(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\n-- stale target: interpretYulRuntimeWithBackend .evmYulLean\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("interpretYulRuntimeWithBackend .evmYulLean" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_accepts_native_theorem_seam(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\n-- theorem target: interpretIRRuntimeNative\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertEqual(errors, []) + + def test_public_theorem_target_guard_rejects_reintroduced_native_fuel_wrapper_obligation(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ndef nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper : Prop := True\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_reintroduced_yul_result_agreement(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ndef yulResultsAgreeOn : Prop := True\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("yulResultsAgreeOn" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_direct_wrapper_fuel_bridge_obligation(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ndef nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper : Prop := True\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("nativeIRRuntimeAgreesWithEvmYulLeanFuelWrapper" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_hidden_ir_runtime_alias(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ndef nativeIRRuntimeAgreesWithEvmYulLean : Prop := True\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("hidden native IR-runtime fuel-wrapper alias" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_simple_storage_native_compat_wrapper(self) -> None: + end_to_end_text = self.replace_in_theorem_signature( + check.END_TO_END.read_text(encoding="utf-8"), + "simpleStorage_endToEnd_native_evmYulLean", + "nativeGeneratedCallDispatcherResultOf", + "Compiler.Proofs.YulGeneration.Backends.Native.interpretIRRuntimeNative", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("nativeGeneratedCallDispatcherResultOf" in error for error in errors), + errors, + ) + self.assertTrue( + any("interpretIRRuntimeNative" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_simple_storage_native_compat_splitter(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "simpleStorageNativeCallDispatcherMatchBridge_of_per_case\n" + " tx initialState observableSlots", + "simpleStorageNativeCallDispatcherBridge_of_per_case\n" + " tx initialState observableSlots", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("CallDispatcherMatchBridge" in error for error in errors), + errors, + ) + self.assertTrue( + any("CallDispatcherBridge" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_misleading_positive_layer3_alias(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ntheorem layer3_contract_preserves_semantics_native_of_generated_dispatcherExec_positive " + + ": True := by trivial\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("positive_match" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_misleading_positive_layers23_alias(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ntheorem layers2_3_ir_matches_native_evmYulLean_of_generated_dispatcherExec_positive " + + ": True := by trivial\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("positive_match" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_removed_simple_storage_bridge_surface(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ndef simpleStorageNativeRetrieveHitBridge : Prop := True\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("obsolete SimpleStorage fuel-wrapper bridge" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_simple_storage_native_scaffold_surface(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\nnoncomputable def simpleStorageNativeDispatcherFuel : Nat := 1\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("dispatcher proof scaffolding" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_source_body_closure_surface(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ndef SourceBodyNativeClosure (_model : Model) (_selectors : List Nat) : Prop := True\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("SourceBodyNativeClosure" in error and "file-local" in error for error in errors), + errors, + ) + + def test_rejects_verity_default_builtin_backend(self) -> None: + builtins_text = check.BUILTINS.read_text(encoding="utf-8").replace( + "private abbrev defaultBuiltinBackend : BuiltinBackend := .evmYulLean", + "private abbrev defaultBuiltinBackend : BuiltinBackend := .verity", + ) + errors = check.check_default_builtin_backend(builtins_text) + self.assertTrue( + any("default builtin backend" in error for error in errors), + errors, + ) + + def test_rejects_public_default_builtin_backend_alias(self) -> None: + builtins_text = check.BUILTINS.read_text(encoding="utf-8").replace( + "private abbrev defaultBuiltinBackend : BuiltinBackend := .evmYulLean", + "abbrev defaultBuiltinBackend : BuiltinBackend := .evmYulLean", + ) + errors = check.check_default_builtin_backend(builtins_text) + self.assertTrue( + any("defaultBuiltinBackend" in error for error in errors), + errors, + ) + + def test_rejects_public_eval_builtin_call_wrapper(self) -> None: + builtins_text = check.BUILTINS.read_text(encoding="utf-8").replace( + "private def evalBuiltinCall", + "def evalBuiltinCall", + 1, + ) + errors = check.check_default_builtin_backend(builtins_text) + self.assertTrue( + any("evalBuiltinCall" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_reintroduced_call_dispatcher_fuel_wrapper(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ndef nativeCallDispatcherAgreesWithEvmYulLeanFuelWrapper : Prop := True\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("nativeCallDispatcherAgreesWithEvmYulLeanFuelWrapper" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_eval_builtin_call_mention(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\n-- stale proof note: evalBuiltinCall\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("evalBuiltinCall" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_reintroduced_dispatcher_block_fuel_wrapper(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ndef nativeDispatcherBlockAgreesWithEvmYulLeanFuelWrapper : Prop := True\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("nativeDispatcherBlockAgreesWithEvmYulLeanFuelWrapper" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_reintroduced_dispatcher_exec_fuel_wrapper(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ndef nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapper : Prop := True\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("nativeDispatcherExecAgreesWithEvmYulLeanFuelWrapper" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_low_level_native_target(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\n-- theorem target: EvmYul.Yul.callDispatcher\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue(any("callDispatcher" in error for error in errors), errors) + + def test_public_theorem_target_guard_rejects_removed_backend_wrapper(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\nprivate theorem layers2_3_ir_matches_yul_evmYulLeanBackend : True := by trivial\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("layers2_3_ir_matches_yul_evmYulLeanBackend" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_native_identity_seam(self) -> None: + end_to_end_text = check.END_TO_END.read_text(encoding="utf-8").replace( + "private theorem layers2_3_ir_matches_native_evmYulLean", + "theorem layers2_3_ir_matches_native_evmYulLean", + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("arbitrary-fuel native identity seam" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_hidden_evmyullean_fuel_alias(self) -> None: + retarget_text = ( + check.RETARGET.read_text(encoding="utf-8") + + "\ndef interpretYulRuntimeEvmYulLean runtimeCode tx storage events := True\n" + ) + errors = check.check_public_theorem_target( + check.END_TO_END.read_text(encoding="utf-8"), + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + retarget_text, + ) + self.assertTrue( + any("interpretYulRuntimeEvmYulLean" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_backend_interpreter_surface(self) -> None: + retarget_text = check.RETARGET.read_text(encoding="utf-8").replace( + "private noncomputable def interpretYulRuntimeWithBackend", + "noncomputable def interpretYulRuntimeWithBackend", + ) + errors = check.check_public_theorem_target( + check.END_TO_END.read_text(encoding="utf-8"), + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + retarget_text, + ) + self.assertTrue( + any("backend-interpreter transition surface" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_backend_fuel_surface(self) -> None: + retarget_text = check.RETARGET.read_text(encoding="utf-8").replace( + "private theorem execYulFuelWithBackend_eq_on_bridged_target", + "theorem execYulFuelWithBackend_eq_on_bridged_target", + ) + errors = check.check_public_theorem_target( + check.END_TO_END.read_text(encoding="utf-8"), + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + retarget_text, + ) + self.assertTrue( + any("backend-interpreter transition surface" in error for error in errors), + errors, + ) + + def test_public_theorem_target_guard_rejects_public_expression_bridge_surface(self) -> None: + retarget_text = check.RETARGET.read_text(encoding="utf-8").replace( + "private theorem evalYulExpr_evmYulLean_eq_on_bridged", + "theorem evalYulExpr_evmYulLean_eq_on_bridged", + ) + errors = check.check_public_theorem_target( + check.END_TO_END.read_text(encoding="utf-8"), + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + retarget_text, + ) + self.assertTrue( + any("backend-interpreter transition surface" in error for error in errors), + errors, + ) + + def test_reference_oracle_names_guard_accepts_current_shape(self) -> None: + errors = check.check_reference_oracle_names( + check.END_TO_END.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + check.PRESERVATION.read_text(encoding="utf-8"), + ) + self.assertEqual(errors, []) + + def test_public_surface_guard_rejects_legacy_reference_oracle_end_to_end_wrapper(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ntheorem layer3_contract_preserves_semantics_via_reference_oracle : True := by trivial\n" + ) + errors = check.check_public_theorem_target( + end_to_end_text, + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("layer3_contract_preserves_semantics_via_reference_oracle" in error for error in errors), + errors, + ) + + def test_reference_oracle_names_guard_rejects_bare_legacy_theorem_name(self) -> None: + preservation_text = check.PRESERVATION.read_text(encoding="utf-8").replace( + "theorem yulCodegen_preserves_semantics_via_reference_oracle", + "theorem yulCodegen_preserves_semantics", + ) + errors = check.check_reference_oracle_names( + check.END_TO_END.read_text(encoding="utf-8"), + check.RETARGET.read_text(encoding="utf-8"), + preservation_text, + ) + self.assertTrue( + any("bare `yulCodegen_preserves_semantics`" in error for error in errors), + errors, + ) + + def test_reference_oracle_names_guard_rejects_reintroduced_evmyullean_retarget(self) -> None: + retarget_text = ( + check.RETARGET.read_text(encoding="utf-8") + + "\nprivate theorem yulCodegen_preserves_semantics_evmYulLeanBackend " + + ": True := by trivial\n" + ) + errors = check.check_reference_oracle_names( + check.END_TO_END.read_text(encoding="utf-8"), + retarget_text, + check.PRESERVATION.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("transition-only legacy Layer-3 retarget theorem" in error for error in errors), + errors, + ) + + def test_reference_oracle_names_guard_rejects_public_evmyullean_retarget(self) -> None: + retarget_text = ( + check.RETARGET.read_text(encoding="utf-8") + + "\ntheorem yulCodegen_preserves_semantics_evmYulLeanBackend " + + ": True := by trivial\n" + ) + errors = check.check_reference_oracle_names( + check.END_TO_END.read_text(encoding="utf-8"), + retarget_text, + check.PRESERVATION.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("transition-only legacy Layer-3 retarget theorem" in error for error in errors), + errors, + ) + + def test_reference_oracle_names_guard_rejects_hidden_evmyullean_alias(self) -> None: + retarget_text = ( + check.RETARGET.read_text(encoding="utf-8") + + "\ntheorem yulCodegen_preserves_semantics_evmYulLean : True := by trivial\n" + ) + errors = check.check_reference_oracle_names( + check.END_TO_END.read_text(encoding="utf-8"), + retarget_text, + check.PRESERVATION.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("hidden reference-oracle compatibility alias" in error for error in errors), + errors, + ) + + def test_reference_oracle_names_guard_rejects_hidden_evmyullean_via_reference_alias(self) -> None: + retarget_text = ( + check.RETARGET.read_text(encoding="utf-8") + + "\ntheorem yulCodegen_preserves_semantics_evmYulLean_via_reference_oracle : True := by trivial\n" + ) + errors = check.check_reference_oracle_names( + check.END_TO_END.read_text(encoding="utf-8"), + retarget_text, + check.PRESERVATION.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("hidden default-fuel compatibility alias" in error for error in errors), + errors, + ) + + def test_reference_oracle_names_guard_rejects_reintroduced_evmyullean_via_reference_retarget(self) -> None: + retarget_text = ( + check.RETARGET.read_text(encoding="utf-8") + + "\nprivate theorem yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle " + + ": True := by trivial\n" + ) + errors = check.check_reference_oracle_names( + check.END_TO_END.read_text(encoding="utf-8"), + retarget_text, + check.PRESERVATION.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("transition-only legacy Layer-3 retarget theorem" in error for error in errors), + errors, + ) + + def test_reference_oracle_names_guard_rejects_end_to_end_compat_alias_call(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\n-- yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle\n" + ) + errors = check.check_reference_oracle_names( + end_to_end_text, + check.RETARGET.read_text(encoding="utf-8"), + check.PRESERVATION.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("legacy compatibility alias" in error for error in errors), + errors, + ) + + def test_reference_oracle_names_guard_rejects_reintroduced_native_layer3_oracle_seam(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ntheorem layer3_contract_preserves_semantics_native_via_reference_oracle_of_evmYulLean_bridge " + + ": True := by trivial\n" + ) + errors = check.check_reference_oracle_names( + end_to_end_text, + check.RETARGET.read_text(encoding="utf-8"), + check.PRESERVATION.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("layer3_contract_preserves_semantics_native_via_reference_oracle_of_evmYulLean_bridge" in error for error in errors), + errors, + ) + + def test_reference_oracle_names_guard_rejects_reintroduced_native_end_to_end_oracle_seam(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\ntheorem layers2_3_ir_matches_native_evmYulLean_via_reference_oracle_of_evmYulLean_bridge " + + ": True := by trivial\n" + ) + errors = check.check_reference_oracle_names( + end_to_end_text, + check.RETARGET.read_text(encoding="utf-8"), + check.PRESERVATION.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("layers2_3_ir_matches_native_evmYulLean_via_reference_oracle_of_evmYulLean_bridge" in error for error in errors), + errors, + ) + + def test_legacy_proof_boundary_accepts_current_shape(self) -> None: + errors = check.check_legacy_proof_boundary( + [ + ("Compiler/Proofs/EndToEnd.lean", check.END_TO_END.read_text(encoding="utf-8")), + ("Compiler.lean", check.ROOT_COMPILER.read_text(encoding="utf-8")), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean", + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean", + check.NATIVE_ADAPTER.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgePredicates.lean", + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean", + check.BODY_CLOSURE.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean", + check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ), + ], + [ + (path.relative_to(check.ROOT).as_posix(), path.read_text(encoding="utf-8")) + for path in check.LEGACY_PROOF_FILES + ], + ) + self.assertEqual(errors, []) + + def test_public_transitive_import_boundary_accepts_current_shape(self) -> None: + errors = check.check_public_transitive_import_boundary( + [ + ("Compiler/Proofs/EndToEnd.lean", check.END_TO_END.read_text(encoding="utf-8")), + ("Compiler.lean", check.ROOT_COMPILER.read_text(encoding="utf-8")), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean", + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean", + check.NATIVE_ADAPTER.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgePredicates.lean", + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean", + check.BODY_CLOSURE.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean", + check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ), + ] + ) + self.assertEqual(errors, []) + + def test_public_transitive_import_boundary_rejects_helper_reaching_bridge_lemmas(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\nimport Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeTest\n" + ) + errors = check.check_public_transitive_import_boundary( + [("Compiler/Proofs/EndToEnd.lean", end_to_end_text)] + ) + self.assertTrue( + any("EvmYulLeanBridgeLemmas" in error for error in errors), + errors, + ) + + def test_public_transitive_import_boundary_rejects_helper_reaching_reference_oracle(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\nimport Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeTest\n" + ) + errors = check.check_public_transitive_import_boundary( + [("Compiler/Proofs/EndToEnd.lean", end_to_end_text)] + ) + self.assertTrue( + any("ReferenceOracle.Builtins" in error for error in errors), + errors, + ) + + def test_transition_only_import_allowlist_accepts_current_shape(self) -> None: + errors = check.check_transition_only_import_allowlist( + [ + (path.relative_to(check.ROOT).as_posix(), path.read_text(encoding="utf-8")) + for path in check.transition_import_scan_files() + ] + ) + self.assertEqual(errors, []) + + def test_transition_only_import_allowlist_rejects_new_bridge_lemmas_importer(self) -> None: + errors = check.check_transition_only_import_allowlist( + [ + ( + "Compiler/Proofs/EndToEnd.lean", + "import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeLemmas\n", + ) + ] + ) + self.assertTrue( + any("transition-only bridge lemma module" in error for error in errors), + errors, + ) + + def test_transition_only_import_allowlist_rejects_new_reference_oracle_importer(self) -> None: + errors = check.check_transition_only_import_allowlist( + [ + ( + "Compiler/Proofs/EndToEnd.lean", + "import Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics\n", + ) + ] + ) + self.assertTrue( + any("legacy ReferenceOracle module" in error for error in errors), + errors, + ) + + def test_public_transitive_forbidden_terms_accepts_current_shape(self) -> None: + errors = check.check_public_transitive_forbidden_terms( + [ + ("Compiler/Proofs/EndToEnd.lean", check.END_TO_END.read_text(encoding="utf-8")), + ("Compiler.lean", check.ROOT_COMPILER.read_text(encoding="utf-8")), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean", + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean", + check.NATIVE_ADAPTER.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBridgePredicates.lean", + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanBodyClosure.lean", + check.BODY_CLOSURE.read_text(encoding="utf-8"), + ), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanSourceExprClosure.lean", + check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ), + ] + ) + self.assertEqual(errors, []) + + def test_public_transitive_forbidden_terms_rejects_adapter_legacy_term(self) -> None: + adapter_text = ( + check.NATIVE_ADAPTER.read_text(encoding="utf-8") + + "\n-- stale proof dependency: interpretYulRuntimeWithBackend .evmYulLean\n" + ) + errors = check.check_public_transitive_forbidden_terms( + [ + ("Compiler.lean", check.ROOT_COMPILER.read_text(encoding="utf-8")), + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean", + adapter_text, + ), + ] + ) + self.assertTrue( + any("interpretYulRuntimeWithBackend" in error for error in errors), + errors, + ) + + def test_public_transitive_forbidden_terms_rejects_native_harness_legacy_term(self) -> None: + native_harness_text = ( + check.NATIVE_HARNESS.read_text(encoding="utf-8") + + "\n-- stale proof dependency: evalBuiltinCallWithContext\n" + ) + errors = check.check_public_transitive_forbidden_terms( + [ + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean", + native_harness_text, + ) + ] + ) + self.assertTrue( + any("evalBuiltinCallWithContext" in error for error in errors), + errors, + ) + + def test_bridge_lemmas_transition_surface_accepts_current_shape(self) -> None: + errors = check.check_bridge_lemmas_transition_surface( + check.BRIDGE_LEMMAS.read_text(encoding="utf-8") + ) + self.assertEqual(errors, []) + + def test_bridge_lemmas_transition_surface_rejects_public_pure_bridge(self) -> None: + bridge_lemmas_text = check.BRIDGE_LEMMAS.read_text(encoding="utf-8").replace( + "private theorem evalBuiltinCallWithBackendContext_evmYulLean_pure_bridge", + "theorem evalBuiltinCallWithBackendContext_evmYulLean_pure_bridge", + 1, + ) + errors = check.check_bridge_lemmas_transition_surface(bridge_lemmas_text) + self.assertTrue( + any("pure_bridge" in error for error in errors), + errors, + ) + + def test_adapter_correctness_transition_surface_accepts_current_shape(self) -> None: + errors = check.check_adapter_correctness_transition_surface( + check.ADAPTER_CORRECTNESS.read_text(encoding="utf-8") + ) + self.assertEqual(errors, []) + + def test_adapter_correctness_transition_surface_rejects_public_helpers(self) -> None: + adapter_correctness_text = ( + check.ADAPTER_CORRECTNESS.read_text(encoding="utf-8") + .replace("private theorem assign_equiv_let", "theorem assign_equiv_let", 1) + .replace( + "@[simp] private theorem legacyExecYulFuel_stmts_nil", + "@[simp] theorem legacyExecYulFuel_stmts_nil", + 1, + ) + ) + errors = check.check_adapter_correctness_transition_surface(adapter_correctness_text) + self.assertTrue( + any("assign_equiv_let" in error for error in errors), + errors, + ) + self.assertTrue( + any("legacyExecYulFuel_stmts_nil" in error for error in errors), + errors, + ) + + def test_native_closure_import_boundary_accepts_current_shape(self) -> None: + errors = check.check_native_closure_import_boundary( + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + check.BODY_CLOSURE.read_text(encoding="utf-8"), + check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ) + self.assertEqual(errors, []) + + def test_native_closure_import_boundary_rejects_legacy_predicate_language(self) -> None: + bridge_text = ( + check.BRIDGE_PREDICATES.read_text(encoding="utf-8") + + "\n/- native and transition backends agree through .verity -/\n" + ) + errors = check.check_native_closure_import_boundary( + bridge_text, + check.BODY_CLOSURE.read_text(encoding="utf-8"), + check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("legacy transition authority language" in error for error in errors), + errors, + ) + + def test_native_closure_import_boundary_rejects_bridge_predicates_ir_interpreter_import(self) -> None: + bridge_text = ( + check.BRIDGE_PREDICATES.read_text(encoding="utf-8").replace( + "import Compiler.Proofs.YulGeneration.LogNames", + "import Compiler.Proofs.IRGeneration.IRInterpreter", + 1, + ) + ) + errors = check.check_native_closure_import_boundary( + bridge_text, + check.BODY_CLOSURE.read_text(encoding="utf-8"), + check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ) + self.assertTrue( + any("full IR interpreter" in error for error in errors), + errors, + ) + + def test_native_closure_import_boundary_rejects_missing_source_keccak_closure(self) -> None: + source_text = check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8").replace( + "theorem compileExpr_keccak256_bridgedSource_of_exprCompileCore", + "theorem compileExpr_keccak256_removed_for_test", + 1, + ) + errors = check.check_native_closure_import_boundary( + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + check.BODY_CLOSURE.read_text(encoding="utf-8"), + source_text, + ) + self.assertTrue( + any( + "compileExpr_keccak256_bridgedSource_of_exprCompileCore" in error + for error in errors + ), + errors, + ) + + def test_native_closure_import_boundary_rejects_missing_source_storage_closure(self) -> None: + source_text = check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8").replace( + "| storage (fieldName : String) : BridgedSourceExpr (.storage fieldName)", + "| storageRemoved (fieldName : String) : BridgedSourceExpr (.storage fieldName)", + 1, + ) + errors = check.check_native_closure_import_boundary( + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + check.BODY_CLOSURE.read_text(encoding="utf-8"), + source_text, + ) + self.assertTrue( + any("BridgedSourceExpr (.storage fieldName)" in error for error in errors), + errors, + ) + + def test_native_closure_import_boundary_rejects_missing_source_array_length_closure(self) -> None: + source_text = check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8").replace( + "| arrayLength (name : String) : BridgedSourceExpr (.arrayLength name)", + "| arrayLengthRemoved (name : String) : BridgedSourceExpr (.arrayLength name)", + 1, + ) + errors = check.check_native_closure_import_boundary( + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + check.BODY_CLOSURE.read_text(encoding="utf-8"), + source_text, + ) + self.assertTrue( + any("arrayLength" in error for error in errors), + errors, + ) + + def test_native_closure_import_boundary_rejects_missing_reserved_exp_closure(self) -> None: + source_text = check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8").replace( + "| builtinExp {base exponent}", + "| builtinExpRemoved {base exponent}", + 1, + ) + errors = check.check_native_closure_import_boundary( + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + check.BODY_CLOSURE.read_text(encoding="utf-8"), + source_text, + ) + self.assertTrue( + any("builtinExp" in error for error in errors), + errors, + ) + + def test_native_closure_import_boundary_rejects_missing_source_storage_array_length_closure(self) -> None: + source_text = check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8").replace( + "| storageArrayLength (fieldName : String) :", + "| storageArrayLengthRemoved (fieldName : String) :", + 1, + ) + errors = check.check_native_closure_import_boundary( + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + check.BODY_CLOSURE.read_text(encoding="utf-8"), + source_text, + ) + self.assertTrue( + any("storageArrayLength" in error for error in errors), + errors, + ) + + def test_native_closure_import_boundary_rejects_missing_source_adt_read_closure(self) -> None: + source_text = check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8").replace( + "| adtTag (adtName storageField : String) :", + "| adtTagRemoved (adtName storageField : String) :", + 1, + ) + errors = check.check_native_closure_import_boundary( + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + check.BODY_CLOSURE.read_text(encoding="utf-8"), + source_text, + ) + self.assertTrue( + any("adtTag" in error for error in errors), + errors, + ) + + def test_native_closure_import_boundary_rejects_missing_body_keccak_closure(self) -> None: + body_text = check.BODY_CLOSURE.read_text(encoding="utf-8").replace( + "theorem bridgedSafeStmts_externalMstoreLetKeccak_of_exprCompileCore", + "theorem bridgedSafeStmts_externalMstoreLetKeccak_removed_for_test", + 1, + ) + errors = check.check_native_closure_import_boundary( + check.BRIDGE_PREDICATES.read_text(encoding="utf-8"), + body_text, + check.SOURCE_EXPR_CLOSURE.read_text(encoding="utf-8"), + ) + self.assertTrue( + any( + "bridgedSafeStmts_externalMstoreLetKeccak_of_exprCompileCore" in error + for error in errors + ), + errors, + ) + + def test_runtime_types_import_boundary_accepts_current_shape(self) -> None: + errors = check.check_runtime_types_import_boundary( + check.RUNTIME_TYPES.read_text(encoding="utf-8") + ) + self.assertEqual(errors, []) + + def test_runtime_types_import_boundary_rejects_ir_interpreter_import(self) -> None: + runtime_types_text = check.RUNTIME_TYPES.read_text(encoding="utf-8").replace( + "import Compiler.Proofs.IRGeneration.IRRuntimeTypes", + "import Compiler.Proofs.IRGeneration.IRInterpreter", + 1, + ) + errors = check.check_runtime_types_import_boundary(runtime_types_text) + self.assertTrue( + any("full IR interpreter" in error for error in errors), + errors, + ) + + def test_native_harness_import_boundary_accepts_current_shape(self) -> None: + errors = check.check_native_harness_import_boundary( + check.NATIVE_HARNESS.read_text(encoding="utf-8") + ) + self.assertEqual(errors, []) + + def test_native_harness_import_boundary_rejects_ir_interpreter_import(self) -> None: + native_harness_text = ( + check.NATIVE_HARNESS.read_text(encoding="utf-8") + + "\nimport Compiler.Proofs.IRGeneration.IRInterpreter\n" + ) + errors = check.check_native_harness_import_boundary(native_harness_text) + self.assertTrue( + any("full IR interpreter" in error for error in errors), + errors, + ) + + def test_root_compiler_import_boundary_accepts_current_shape(self) -> None: + errors = check.check_root_compiler_import_boundary( + check.ROOT_COMPILER.read_text(encoding="utf-8") + ) + self.assertEqual(errors, []) + + def test_root_compiler_import_boundary_rejects_direct_ir_interpreter_import(self) -> None: + root_text = ( + check.ROOT_COMPILER.read_text(encoding="utf-8") + + "\nimport Compiler.Proofs.IRGeneration.IRInterpreter\n" + ) + errors = check.check_root_compiler_import_boundary(root_text) + self.assertTrue( + any("full IR interpreter" in error for error in errors), + errors, + ) + + def test_legacy_proof_boundary_rejects_public_boundary_import(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\nimport Compiler.Proofs.YulGeneration.Equivalence\n" + ) + errors = check.check_legacy_proof_boundary( + [("Compiler/Proofs/EndToEnd.lean", end_to_end_text)], + [ + (path.relative_to(check.ROOT).as_posix(), path.read_text(encoding="utf-8")) + for path in check.LEGACY_PROOF_FILES + ], + ) + self.assertTrue( + any("transition-only legacy proof module" in error for error in errors), + errors, + ) + + def test_legacy_proof_boundary_rejects_end_to_end_retarget_import(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + "\nimport Compiler.Proofs.YulGeneration.Backends.EvmYulLeanRetarget\n" + ) + errors = check.check_legacy_proof_boundary( + [("Compiler/Proofs/EndToEnd.lean", end_to_end_text)], + [ + (path.relative_to(check.ROOT).as_posix(), path.read_text(encoding="utf-8")) + for path in check.LEGACY_PROOF_FILES + ], + ) + self.assertTrue( + any("EvmYulLeanRetarget" in error for error in errors), + errors, + ) + + def test_legacy_proof_boundary_rejects_root_retarget_import(self) -> None: + root_compiler_text = ( + check.ROOT_COMPILER.read_text(encoding="utf-8") + + "\nimport Compiler.Proofs.YulGeneration.Backends.EvmYulLeanRetarget\n" + ) + errors = check.check_legacy_proof_boundary( + [("Compiler.lean", root_compiler_text)], + [ + (path.relative_to(check.ROOT).as_posix(), path.read_text(encoding="utf-8")) + for path in check.LEGACY_PROOF_FILES + ], + ) + self.assertTrue( + any("EvmYulLeanRetarget" in error for error in errors), + errors, + ) + + def test_legacy_proof_boundary_rejects_root_bridge_lemmas_import(self) -> None: + root_compiler_text = ( + check.ROOT_COMPILER.read_text(encoding="utf-8") + + "\nimport Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBridgeLemmas\n" + ) + errors = check.check_legacy_proof_boundary( + [("Compiler.lean", root_compiler_text)], + [ + (path.relative_to(check.ROOT).as_posix(), path.read_text(encoding="utf-8")) + for path in check.LEGACY_PROOF_FILES + ], + ) + self.assertTrue( + any("EvmYulLeanBridgeLemmas" in error for error in errors), + errors, + ) + + def test_legacy_proof_boundary_rejects_adapter_reference_oracle_import(self) -> None: + adapter_text = ( + check.NATIVE_ADAPTER.read_text(encoding="utf-8") + + "\nimport Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins\n" + ) + errors = check.check_legacy_proof_boundary( + [ + ( + "Compiler/Proofs/YulGeneration/Backends/EvmYulLeanAdapter.lean", + adapter_text, + ) + ], + [ + (path.relative_to(check.ROOT).as_posix(), path.read_text(encoding="utf-8")) + for path in check.LEGACY_PROOF_FILES + ], + ) + self.assertTrue( + any("legacy ReferenceOracle modules" in error for error in errors), + errors, + ) + + def test_legacy_proof_boundary_rejects_root_reference_oracle_import(self) -> None: + root_compiler_text = ( + check.ROOT_COMPILER.read_text(encoding="utf-8") + + "\nimport Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics\n" + ) + errors = check.check_legacy_proof_boundary( + [("Compiler.lean", root_compiler_text)], + [ + (path.relative_to(check.ROOT).as_posix(), path.read_text(encoding="utf-8")) + for path in check.LEGACY_PROOF_FILES + ], + ) + self.assertTrue( + any("legacy ReferenceOracle modules" in error for error in errors), + errors, + ) + + def test_legacy_proof_boundary_rejects_public_legacy_declaration(self) -> None: + legacy_text = ( + check.LEGACY_PROOF_FILES[1].read_text(encoding="utf-8") + + "\ntheorem leakedLegacyTransitionAuthority : True := by trivial\n" + ) + errors = check.check_legacy_proof_boundary( + [], + [("Compiler/Proofs/YulGeneration/Equivalence.lean", legacy_text)], + ) + self.assertTrue( + any("leakedLegacyTransitionAuthority" in error for error in errors), + errors, + ) + + def test_legacy_proof_boundary_rejects_public_attributed_legacy_declaration(self) -> None: + legacy_text = ( + check.LEGACY_PROOF_FILES[0].read_text(encoding="utf-8") + + "\n@[simp] theorem leakedLegacyFuelSimp : True := by trivial\n" + ) + errors = check.check_legacy_proof_boundary( + [], + [("Compiler/Proofs/YulGeneration/Codegen.lean", legacy_text)], + ) + self.assertTrue( + any("leakedLegacyFuelSimp" in error for error in errors), + errors, + ) + + def test_native_alias_signature_guard_accepts_current_shape(self) -> None: + errors = check.check_native_alias_signatures( + check.END_TO_END.read_text(encoding="utf-8"), + ) + self.assertEqual(errors, []) + + def test_native_alias_signature_guard_rejects_hidden_dispatcher_alias(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + """ +theorem nativeAliasSurfaceForTestEvmYulLean + (h : + nativeDispatcherExecAgreesWithEvmYulLean fuel contract tx state + observableSlots nativeContract) : + True := by + trivial +""" + ) + errors = check.check_native_alias_signatures(end_to_end_text) + self.assertTrue( + any("nativeDispatcherExecAgreesWithEvmYulLean" in error for error in errors), + errors, + ) + + def test_native_alias_signature_guard_rejects_lowercase_evmYulLean_name(self) -> None: + end_to_end_text = """ +theorem nativeAliasSurfaceForTest_evmYulLean + (h : + nativeDispatcherExecAgreesWithEvmYulLean fuel contract tx state + observableSlots nativeContract) : + True := by + trivial +""" + errors = check.check_native_alias_signatures(end_to_end_text) + self.assertTrue( + any("nativeDispatcherExecAgreesWithEvmYulLean" in error for error in errors), + errors, + ) + + def test_native_alias_signature_guard_allows_direct_match_theorem(self) -> None: + end_to_end_text = """ +theorem nativeAliasSurfaceForTestEvmYulLeanMatch + (h : + nativeDispatcherExecMatchesIRPositive fuel contract tx state + observableSlots nativeContract) : + True := by + trivial +""" + errors = check.check_native_alias_signatures(end_to_end_text) + self.assertEqual(errors, []) + + def test_public_end_to_end_theorem_signature_guard_accepts_current_shape(self) -> None: + errors = check.check_public_end_to_end_theorem_signatures( + check.END_TO_END.read_text(encoding="utf-8"), + ) + self.assertEqual(errors, []) + + def test_public_end_to_end_theorem_signature_guard_rejects_legacy_terms(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + """ +theorem legacySignatureSurfaceForTest + (h : + Compiler.Proofs.YulGeneration.ReferenceOracle.Semantics.execYulFuelWithBackend + .verity fuel stmts tx state = .ok result) : + True := by + trivial +""" + ) + errors = check.check_public_end_to_end_theorem_signatures(end_to_end_text) + self.assertTrue( + any(".verity" in error and "execYulFuel" in error for error in errors), + errors, + ) + + def test_public_end_to_end_theorem_signature_guard_rejects_arbitrary_fuel(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + """ +theorem arbitraryFuelSurfaceForTest + (fuel : Nat) + (hNative : nativeResultsMatchOn observableSlots ir native) : + True := by + trivial +""" + ) + errors = check.check_public_end_to_end_theorem_signatures(end_to_end_text) + self.assertTrue( + any("arbitrary theorem-facing fuel" in error for error in errors), + errors, + ) + + def test_public_end_to_end_theorem_signature_guard_rejects_call_dispatcher_body_env_terms(self) -> None: + end_to_end_text = ( + check.END_TO_END.read_text(encoding="utf-8") + + """ +theorem compile_preserves_native_evmYulLean_callDispatcher_of_generated_callDispatcher_match + (_hBodies : SourceBodyNativeClosure model selectors) + (_hEnv : + Compiler.Proofs.YulGeneration.Backends.Native.nativeRuntimePathUsesUnsupportedHeaderBuiltin + runtime tx = false) : + True := by + trivial +""" + ) + errors = check.check_public_end_to_end_theorem_signatures(end_to_end_text) + self.assertTrue( + any("SourceBodyNativeClosure" in error for error in errors), + errors, + ) + self.assertTrue( + any("nativeRuntimePathUsesUnsupportedHeaderBuiltin" in error for error in errors), + errors, + ) + + def test_unbridged_environment_boundary_accepts_current_shape(self) -> None: + errors = check.check_unbridged_environment_boundary( + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + check.NATIVE_SMOKE_TEST.read_text(encoding="utf-8"), + ) + self.assertEqual(errors, []) + + def test_unbridged_environment_boundary_rejects_missing_chainid_rejection_pin(self) -> None: + smoke_text = check.NATIVE_SMOKE_TEST.read_text(encoding="utf-8").replace( + 'nativeRejectsUnsupportedChainId = true', + 'nativeAcceptsUnsupportedChainId = true', + ) + errors = check.check_unbridged_environment_boundary( + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + smoke_text, + ) + self.assertTrue(any("chainid" in error.lower() for error in errors), errors) + + def test_unbridged_environment_boundary_rejects_missing_blobbasefee_rejection_pin(self) -> None: + smoke_text = check.NATIVE_SMOKE_TEST.read_text(encoding="utf-8").replace( + 'nativeRejectsUnsupportedBlobBaseFee = true', + 'nativeAcceptsUnsupportedBlobBaseFee = true', + ) + errors = check.check_unbridged_environment_boundary( + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + smoke_text, + ) + self.assertTrue(any("blobbasefee" in error for error in errors), errors) + + def test_unbridged_environment_boundary_rejects_missing_selfbalance_rejection_pin(self) -> None: + smoke_text = check.NATIVE_SMOKE_TEST.read_text(encoding="utf-8").replace( + 'nativeRejectsUnsupportedHeaderBuiltin "selfbalance" = true', + 'nativeAcceptsUnsupportedHeaderBuiltin "selfbalance" = true', + ) + errors = check.check_unbridged_environment_boundary( + check.NATIVE_HARNESS.read_text(encoding="utf-8"), + smoke_text, + ) + self.assertTrue(any("selfbalance" in error for error in errors), errors) def test_native_switch_lowering_boundary_accepts_current_shape(self) -> None: errors = check.check_native_switch_lowering_boundary( diff --git a/scripts/test_check_solc_pin.py b/scripts/test_check_solc_pin.py index 10bd5e4bd..605c0cb0f 100644 --- a/scripts/test_check_solc_pin.py +++ b/scripts/test_check_solc_pin.py @@ -20,6 +20,7 @@ def _run( self, *, extra_verify_env: str = "", + action_body: str | None = None, ) -> tuple[int, str, str]: with tempfile.TemporaryDirectory() as tmpdir: root = Path(tmpdir) @@ -48,17 +49,20 @@ def _run( encoding="utf-8", ) action.write_text( - "\n".join( - [ - "name: setup-solc", - "runs:", - " using: composite", - " steps:", - " - shell: bash", - " run: |", - ' curl -sSfL "$SOLC_URL" -o solc', - ' echo "${SOLC_SHA256} solc" | sha256sum -c -', - ] + ( + action_body + or "\n".join( + [ + "name: setup-solc", + "runs:", + " using: composite", + " steps:", + " - shell: bash", + " run: |", + ' curl -sSfL "$SOLC_URL" -o solc', + ' echo "${SOLC_SHA256} solc" | sha256sum -c -', + ] + ) ) + "\n", encoding="utf-8", @@ -120,6 +124,26 @@ def test_allows_duplicate_assignments_when_values_match(self) -> None: self.assertIn("solc pin is consistent", stdout) self.assertEqual(stderr, "") + def test_rejects_privileged_solc_install_path(self) -> None: + rc, _stdout, stderr = self._run( + action_body="\n".join( + [ + "name: setup-solc", + "runs:", + " using: composite", + " steps:", + " - shell: bash", + " run: |", + ' curl -sSfL "$SOLC_URL" -o solc', + ' echo "${SOLC_SHA256} solc" | sha256sum -c -', + " sudo mv solc /usr/local/bin/solc", + ] + ) + ) + self.assertEqual(rc, 1) + self.assertIn("workspace-local", stderr) + self.assertIn("must not require sudo", stderr) + if __name__ == "__main__": unittest.main() diff --git a/scripts/test_check_yul.py b/scripts/test_check_yul.py index 6f9c8f686..cea4858ca 100644 --- a/scripts/test_check_yul.py +++ b/scripts/test_check_yul.py @@ -18,6 +18,11 @@ class YulChecksTests(unittest.TestCase): + NATIVE_BODY = """import Compiler.Proofs.YulGeneration.Backends.EvmYulLeanBuiltinSemantics +def evalExpr := + Compiler.Proofs.YulGeneration.Backends.evalBuiltinCallWithEvmYulLeanContext +""" + def _run_boundary_check(self, ir_body: str, sem_body: str) -> list[str]: with tempfile.TemporaryDirectory(dir=property_utils.ROOT) as tmpdir: root = Path(tmpdir) @@ -54,14 +59,14 @@ def test_comment_only_decoy_does_not_satisfy_boundary(self) -> None: -- decoy only: Compiler.Proofs.YulGeneration.evalBuiltinCall def evalExpr := 0 """ - failures = self._run_boundary_check(body, body) + failures = self._run_boundary_check(self.NATIVE_BODY, body) self.assertTrue(any("missing call" in failure for failure in failures)) def test_string_literal_decoy_does_not_satisfy_boundary(self) -> None: body = """import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins def evalExpr := "Compiler.Proofs.YulGeneration.evalBuiltinCall" """ - failures = self._run_boundary_check(body, body) + failures = self._run_boundary_check(self.NATIVE_BODY, body) self.assertTrue(any("missing call" in failure for failure in failures)) def test_eval_builtin_call_with_backend_satisfies_boundary(self) -> None: @@ -69,7 +74,7 @@ def test_eval_builtin_call_with_backend_satisfies_boundary(self) -> None: def evalExpr := Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackend """ - failures = self._run_boundary_check(body, body) + failures = self._run_boundary_check(self.NATIVE_BODY, body) self.assertEqual(failures, []) def test_eval_builtin_call_with_backend_context_satisfies_boundary(self) -> None: @@ -77,7 +82,15 @@ def test_eval_builtin_call_with_backend_context_satisfies_boundary(self) -> None def evalExpr := Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext """ - failures = self._run_boundary_check(body, body) + failures = self._run_boundary_check(self.NATIVE_BODY, body) + self.assertEqual(failures, []) + + def test_native_ir_interpreter_boundary(self) -> None: + legacy_body = """import Compiler.Proofs.YulGeneration.ReferenceOracle.Builtins +def evalExpr := + Compiler.Proofs.YulGeneration.evalBuiltinCallWithBackendContext +""" + failures = self._run_boundary_check(self.NATIVE_BODY, legacy_body) self.assertEqual(failures, []) def test_inline_dispatch_regex_covers_env_builtins(self) -> None: diff --git a/scripts/test_evmyullean_capability.py b/scripts/test_evmyullean_capability.py index aa2242106..3ce360b60 100644 --- a/scripts/test_evmyullean_capability.py +++ b/scripts/test_evmyullean_capability.py @@ -29,7 +29,7 @@ def test_extract_found_builtins_resolves_alias_literal(self) -> None: builtins_file = Path(tmpdir) / "Builtins.lean" builtins_file.write_text( "namespace X\n\n" - "def evalBuiltinCall (func : String) (argVals : List Nat) : Option Nat :=\n" + "def legacyEvalBuiltinCallWithContext (func : String) (argVals : List Nat) : Option Nat :=\n" " let op := \"create\"\n" " if func = op then\n" " some 1\n" @@ -44,6 +44,24 @@ def test_extract_found_builtins_resolves_alias_literal(self) -> None: self.assertEqual(found, {"create"}) self.assertEqual(diagnostics, []) + def test_extract_found_builtins_ignores_backend_context_prefix(self) -> None: + with tempfile.TemporaryDirectory(dir=property_utils.ROOT) as tmpdir: + builtins_file = Path(tmpdir) / "Builtins.lean" + builtins_file.write_text( + "namespace X\n\n" + "def evalBuiltinCallWithBackendContext (func : String) : Option Nat :=\n" + " if func = \"address\" then some 1 else none\n\n" + "def legacyEvalBuiltinCallWithContext (func : String) : Option Nat :=\n" + " if func = \"add\" then some 1 else none\n", + encoding="utf-8", + ) + + found, diagnostics = evmyullean_capability.extract_found_builtins_with_diagnostics( + builtins_file + ) + self.assertEqual(found, {"add"}) + self.assertEqual(diagnostics, []) + def test_extract_found_builtins_reports_unresolved_non_literal_dispatch(self) -> None: with tempfile.TemporaryDirectory(dir=property_utils.ROOT) as tmpdir: builtins_file = Path(tmpdir) / "Builtins.lean" @@ -63,6 +81,25 @@ def test_extract_found_builtins_reports_unresolved_non_literal_dispatch(self) -> self.assertEqual(len(diagnostics), 1) self.assertIn("non-literal dispatch", diagnostics[0]) + def test_extract_found_builtins_accepts_private_eval_builtin_call(self) -> None: + with tempfile.TemporaryDirectory(dir=property_utils.ROOT) as tmpdir: + builtins_file = Path(tmpdir) / "Builtins.lean" + builtins_file.write_text( + "namespace X\n\n" + "private def evalBuiltinCall (func : String) (argVals : List Nat) : Option Nat :=\n" + " if func = \"calldatasize\" then\n" + " some 1\n" + " else\n" + " none\n", + encoding="utf-8", + ) + + found, diagnostics = evmyullean_capability.extract_found_builtins_with_diagnostics( + builtins_file + ) + self.assertEqual(found, {"calldatasize"}) + self.assertEqual(diagnostics, []) + def test_extract_found_builtins_resolves_typed_alias_chain(self) -> None: with tempfile.TemporaryDirectory(dir=property_utils.ROOT) as tmpdir: builtins_file = Path(tmpdir) / "Builtins.lean" diff --git a/scripts/test_generate_evmyullean_adapter_report.py b/scripts/test_generate_evmyullean_adapter_report.py index d1f0a6175..d1d355686 100644 --- a/scripts/test_generate_evmyullean_adapter_report.py +++ b/scripts/test_generate_evmyullean_adapter_report.py @@ -766,7 +766,18 @@ def test_scalar_parameter_body_closure_is_tracked(self) -> None: ) self.assertEqual( phase4["compileExpr_bridgedSource"], - "proven (pure source-expression fragment)", + "proven (source-expression fragment with parameter length, " + "storage, and storage-array length reads, ADT tag/field reads, " + "singleton and nested mapping reads through the abstract " + "mappingSlot bridge, mapping struct-member reads, " + "reserved exponentiation, boolean normalization, branchless " + "helpers, bridged environment reads, and unary calldata/memory/" + "transient reads)", + ) + self.assertEqual( + phase4["compileExpr_mappingChain_bridgedSource"], + "proven (mappingChain source-expression wrapper through " + "the abstract mappingSlot bridge)", ) def test_missing_retarget_theorem_is_not_reported_proven(self) -> None: @@ -815,7 +826,7 @@ def test_missing_retarget_theorem_is_not_reported_proven(self) -> None: "missing", ) self.assertEqual( - phase4["yulCodegen_preserves_semantics_evmYulLean"], + phase4["yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle"], "missing", ) @@ -872,7 +883,7 @@ def test_sorry_retarget_theorem_downgrades_phase4_status(self) -> None: theorem emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies : True := by trivial - theorem yulCodegen_preserves_semantics_evmYulLean : True := by + theorem yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle : True := by trivial """), encoding="utf-8", @@ -917,7 +928,7 @@ def test_sorry_retarget_theorem_downgrades_phase4_status(self) -> None: "proven (conditional on bridged IR bodies)", ) self.assertEqual( - phase4["yulCodegen_preserves_semantics_evmYulLean"], + phase4["yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle"], "proven (conditional on bridged IR bodies)", ) self.assertEqual(phase4["admitted_bridge_dependencies"], []) @@ -1045,7 +1056,7 @@ def test_admitted_bridge_deps_downgrade_phase4_status(self) -> None: theorem emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies : True := by trivial - theorem yulCodegen_preserves_semantics_evmYulLean : True := by + theorem yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle : True := by trivial """), encoding="utf-8", @@ -1096,7 +1107,7 @@ def test_admitted_bridge_deps_downgrade_phase4_status(self) -> None: ) self.assertIn( "smod", - phase4["yulCodegen_preserves_semantics_evmYulLean"], + phase4["yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle"], ) def test_universal_body_closure_proven_in_repo(self) -> None: @@ -1104,10 +1115,11 @@ def test_universal_body_closure_proven_in_repo(self) -> None: report = gen.build_report() phase4 = report["phase4_retarget"] self.assertIn("proven", phase4["compileStmtList_always_bridged"]) - self.assertEqual(phase4["status"], "full_semantic_integration") + self.assertEqual(phase4["status"], "universal-safe-body-closure") self.assertEqual( - phase4["layers2_3_ir_matches_yul_evmYulLean"], - "proven (body hypotheses discharged)", + phase4["layers2_3_ir_matches_yul_evmYulLeanBackend"], + "removed from EndToEnd surface " + "(retarget evidence isolated in EvmYulLeanRetarget.lean)", ) def _retarget_all_proven(self) -> str: @@ -1142,7 +1154,7 @@ def _retarget_all_proven(self) -> str: theorem emitYul_runtimeCode_evmYulLean_eq_on_bridged_bodies : True := by trivial - theorem yulCodegen_preserves_semantics_evmYulLean : True := by + theorem yulCodegen_preserves_semantics_evmYulLeanBackend_via_reference_oracle : True := by trivial """) @@ -1159,7 +1171,7 @@ def test_universal_body_closure_flips_phase4_status(self) -> None: end_to_end = tmp_path / "EndToEnd.lean" end_to_end.write_text( textwrap.dedent("""\ - theorem layers2_3_ir_matches_yul_evmYulLean : True := by + theorem layers2_3_ir_matches_yul_evmYulLeanBackend : True := by trivial """), encoding="utf-8", @@ -1203,7 +1215,7 @@ def test_universal_body_closure_with_sorry_does_not_flip_phase4_status(self) -> end_to_end = tmp_path / "EndToEnd.lean" end_to_end.write_text( textwrap.dedent("""\ - theorem layers2_3_ir_matches_yul_evmYulLean : True := by + theorem layers2_3_ir_matches_yul_evmYulLeanBackend : True := by trivial """), encoding="utf-8", @@ -1242,7 +1254,7 @@ def test_body_closure_with_conditional_end_to_end_does_not_flip_to_full(self) -> end_to_end = tmp_path / "EndToEnd.lean" end_to_end.write_text( textwrap.dedent("""\ - theorem layers2_3_ir_matches_yul_evmYulLean + theorem layers2_3_ir_matches_yul_evmYulLeanBackend (hFunctions : BridgedStmts body) (hInternals : BridgedStmts internals) : True := by trivial @@ -1271,10 +1283,53 @@ def test_body_closure_with_conditional_end_to_end_does_not_flip_to_full(self) -> phase4 = report["phase4_retarget"] self.assertEqual(phase4["status"], "universal-safe-body-closure") self.assertEqual( - phase4["layers2_3_ir_matches_yul_evmYulLean"], + phase4["layers2_3_ir_matches_yul_evmYulLeanBackend"], "proven (conditional on bridged IR bodies)", ) + def test_body_closure_without_end_to_end_backend_wrapper_stays_universal(self) -> None: + """EndToEnd no longer needs the backend-wrapper theorem for the + universal safe-body closure milestone.""" + with tempfile.TemporaryDirectory(dir=gen.ROOT) as tmp: + tmp_path = Path(tmp) + retarget = tmp_path / "EvmYulLeanRetarget.lean" + retarget.write_text(self._retarget_all_proven(), encoding="utf-8") + + end_to_end = tmp_path / "EndToEnd.lean" + end_to_end.write_text( + textwrap.dedent("""\ + theorem layers2_3_ir_matches_native_evmYulLean : True := by + trivial + """), + encoding="utf-8", + ) + + body_closure = tmp_path / "EvmYulLeanBodyClosure.lean" + body_closure.write_text( + textwrap.dedent("""\ + theorem compileStmtList_always_bridged : True := by + trivial + """), + encoding="utf-8", + ) + + with patch.object(gen, "RETARGET_FILE", retarget), \ + patch.object(gen, "END_TO_END_FILE", end_to_end), \ + patch.object(gen, "BODY_CLOSURE_FILE", body_closure), \ + patch.object( + gen, + "_parse_bridge_lemmas", + return_value=(["add"], []), + ): + report = gen.build_report() + phase4 = report["phase4_retarget"] + self.assertEqual(phase4["status"], "universal-safe-body-closure") + self.assertEqual( + phase4["layers2_3_ir_matches_yul_evmYulLeanBackend"], + "removed from EndToEnd surface " + "(retarget evidence isolated in EvmYulLeanRetarget.lean)", + ) + def test_universal_body_closure_with_admitted_deps_does_not_flip(self) -> None: """If compileStmtList_always_bridged is proven but sar remains admitted, phase4 status must not advance to full_semantic_integration.""" @@ -1286,7 +1341,7 @@ def test_universal_body_closure_with_admitted_deps_does_not_flip(self) -> None: end_to_end = tmp_path / "EndToEnd.lean" end_to_end.write_text( textwrap.dedent("""\ - theorem layers2_3_ir_matches_yul_evmYulLean : True := by + theorem layers2_3_ir_matches_yul_evmYulLeanBackend : True := by trivial """), encoding="utf-8", @@ -1406,7 +1461,7 @@ def bridgedBuiltins : List String := def unbridgedBuiltins : List String := ["sload", "mappingSlot"] """) - with patch.object(gen, "BRIDGE_LEMMAS_FILE", p): + with patch.object(gen, "BRIDGE_PREDICATES_FILE", p): bridged, unbridged = gen._parse_bridged_builtins_defs() self.assertEqual(bridged, ["add", "caller", "sub"]) self.assertEqual(unbridged, ["mappingSlot", "sload"]) @@ -1416,7 +1471,7 @@ def test_missing_defs_return_empty(self) -> None: -- no defs here theorem foo := by sorry """) - with patch.object(gen, "BRIDGE_LEMMAS_FILE", p): + with patch.object(gen, "BRIDGE_PREDICATES_FILE", p): bridged, unbridged = gen._parse_bridged_builtins_defs() self.assertEqual(bridged, []) self.assertEqual(unbridged, []) diff --git a/scripts/test_prune_lake_cache.py b/scripts/test_prune_lake_cache.py index 4b1f7829c..a7bc5e688 100644 --- a/scripts/test_prune_lake_cache.py +++ b/scripts/test_prune_lake_cache.py @@ -69,6 +69,39 @@ def test_prunes_mismatched_package_and_dependency_build_outputs(self) -> None: self.assertFalse(pkg_dir.exists()) self.assertFalse(root_build.exists()) + def test_packages_only_prunes_bad_packages_without_clearing_build(self) -> None: + with tempfile.TemporaryDirectory() as tmpdir: + root = Path(tmpdir) + lake_dir = root / ".lake" + packages_dir = lake_dir / "packages" + pkg_dir = packages_dir / "demo" + pkg_dir.mkdir(parents=True) + root_build = lake_dir / "build" + root_build.mkdir(parents=True) + manifest = root / "lake-manifest.json" + manifest.write_text( + json.dumps( + { + "packages": [ + {"type": "git", "name": "demo", "rev": "expected-rev"}, + ] + } + ) + ) + + with ( + mock.patch.object(prune_lake_cache, "ROOT", root), + mock.patch.object(prune_lake_cache, "LAKE_DIR", lake_dir), + mock.patch.object(prune_lake_cache, "PACKAGES_DIR", packages_dir), + mock.patch.object(prune_lake_cache, "MANIFEST", manifest), + mock.patch.object(prune_lake_cache, "git_head", return_value=None), + ): + rc = prune_lake_cache.main(["--packages-only"]) + + self.assertEqual(rc, 0) + self.assertFalse(pkg_dir.exists()) + self.assertTrue(root_build.exists()) + if __name__ == "__main__": unittest.main() diff --git a/scripts/verify_sync_spec.json b/scripts/verify_sync_spec.json index 3ea4d3c57..164b7a9e0 100644 --- a/scripts/verify_sync_spec.json +++ b/scripts/verify_sync_spec.json @@ -177,7 +177,7 @@ }, "expected_job_timeouts": { "changes": 5, - "checks": 5, + "checks": 10, "timeout-watchdog": 5, "build": "${{ fromJSON(github.event_name == 'workflow_dispatch' && inputs.clean_build && '60' || '35') }}", "prepare-macro-fuzz": 360, diff --git a/scripts/verify_sync_spec_source.py b/scripts/verify_sync_spec_source.py index 0cd9a84e4..2753fd7ad 100644 --- a/scripts/verify_sync_spec_source.py +++ b/scripts/verify_sync_spec_source.py @@ -162,7 +162,7 @@ 'foundry-multi-seed': '[self-hosted, linux, x64, verity, build]', 'failure-hints': '[self-hosted, linux, ARM64, dgx-spark, verity, fastlane]'}, 'expected_job_timeouts': {'changes': 5, - 'checks': 5, + 'checks': 10, 'timeout-watchdog': 5, 'build': "${{ fromJSON(github.event_name == 'workflow_dispatch' && inputs.clean_build && '60' || '35') }}", 'prepare-macro-fuzz': 360,