Skip to content

Target native EVMYulLean runtime for generated Yul #1737

@Th0rgal

Description

@Th0rgal

Goal

Make EVMYulLean's native Yul runtime/interpreter the authoritative Layer 3 execution target for Verity-generated runtime Yul, instead of executing Verity's custom Yul statement interpreter with an EVMYulLean-backed builtin backend.

This follows up #1722, which was auto-closed by #1725. #1725 substantially improved the EVMYulLean builtin bridge, but it did not switch Verity to EvmYul.Yul.exec / EvmYul.Yul.callDispatcher as the runtime target.

Current status after #1725

  • Verity has EVMYulLean-backed builtin coverage for the current safe fragment.
  • The public Layer 3 retargeting path still runs Verity-shaped YulStmt, YulState, and YulResult through interpretYulRuntimeWithBackend .evmYulLean.
  • The EVMYulLean-native interpreter exists and builds:
    • EvmYul.Yul.eval
    • EvmYul.Yul.exec
    • EvmYul.Yul.execTopLevel
    • EvmYul.Yul.callDispatcher
  • The existing adapter is structural, not a complete native-runtime bridge.

Required migration plan

Phase 1: Native runtime harness

Add a separate native execution path without disturbing the proven #1725 path yet.

  • Implement primop-aware lowering from Verity Yul expressions to EVMYulLean expressions.
    • Known builtins must lower to .Call (.inl primOp) ... using lookupPrimOp or an explicit verified mapping.
    • Unknown names should remain .Call (.inr functionName) ... for user/helper Yul functions.
  • Lower generated runtime code into an EVMYulLean YulContract.
    • Partition top-level function definitions into YulContract.functions.
    • Put non-function top-level runtime statements into the dispatcher.
  • Build a native initial-state bridge from Verity transaction/state inputs into EvmYul.Yul.State.Ok.
    • Install the current contract code in the native account/code map.
    • Populate calldata, callvalue, caller/source, address, storage, memory, returndata, block/env fields, and static-call permissions.
  • Define native result projection back to Verity's observable YulResult shape.
    • Return/stop/revert status
    • Return data/value projection
    • Storage changes and revert rollback
    • Logs/events
  • Add executable smoke tests around EvmYul.Yul.exec / EvmYul.Yul.callDispatcher for return, storage, dispatcher selection, mapping helpers, and event logs.

Backup option: keep this as a CI smoke-test runner first, while #1725's theorem remains the public target.

Phase 2: Bridge native execution to current observable semantics

  • Prove syntactic lowering invariants:
    • no top-level funcDef remains in the dispatcher,
    • helper functions are present in YulContract.functions,
    • builtin calls lower to native primops.
  • Prove state bridge lemmas for calldata, selector, sender/source, callvalue, address, block fields, storage lookup, memory, and returndata.
  • Prove result projection lemmas for return, stop, revert, storage, and logs.

Backup option: start with a read-only/no-storage fragment, then widen to storage and events.

Phase 3: Add a public native target theorem

Introduce a native target function, conceptually:

interpretYulRuntimeNativeEvmYulLean :
  List Compiler.Yul.YulStmt →
  YulTransaction →
  (Nat → Nat) →
  List (List Nat) →
  YulResult

Internally this should lower to an EVMYulLean YulContract, build native state, run EvmYul.Yul.callDispatcher or EvmYul.Yul.exec, and project the result.

Then prove the Layer 3 preservation theorem against this native target for the same safe fragment covered by #1725.

Backup option: first prove equivalence between interpretYulRuntimeWithBackend .evmYulLean and the native target, then retarget Layer 3 directly later.

Phase 4: Flip the trusted path

  • Make the native EVMYulLean theorem the canonical end-to-end target.
  • Move Verity's custom Yul interpreter to reference-oracle/regression-test status.
  • Update TRUST_ASSUMPTIONS.md to document EVMYulLean as the semantic trust boundary.
  • Keep the old interpreter for one release cycle as a cross-check.

Phase 5: Cleanup and upstream/fork work

  • Delete or archive the old interpreter only after the proof imports no longer depend on it.
  • Push any required EVMYulLean fork fixes upstream where appropriate.
  • Add conformance/cross-check CI coverage for the native path.

Known blockers / design questions

  • The current adapter lowers all calls as user functions, which fails native execution for builtins such as add.
  • Top-level function definitions are currently not preserved as EVMYulLean contract functions.
  • Full native state construction and result projection are incomplete.
  • Runtime Yul is the right first target. Deploy/object-code intrinsics such as dataoffset, datasize, and datacopy should stay out of the initial migration.
  • Review the EVMYulLean fork for missing primops/notations such as log0, external-call failure semantics, nested static-call behavior, and whether execTopLevel erases too much information for proof use.

Success criteria

  • Native EVMYulLean runtime smoke tests execute generated Verity runtime Yul through EvmYul.Yul.exec / callDispatcher.
  • Runtime lowering builds an EVMYulLean YulContract with dispatcher and functions.
  • State bridge and result projection are defined and tested.
  • A public theorem targets native EVMYulLean execution, not Verity's custom Yul interpreter.
  • TRUST_ASSUMPTIONS.md reflects the reduced trusted surface.
  • The old Verity Yul interpreter is removed from the trusted proof path or explicitly documented as a reference oracle only.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions