A Lean 4 formalization of FOCIL, the consensus-layer
censorship-resistance mechanism specified in
EIP-7805 (the headline
feature of Ethereum's late-2026 Hegotá hard fork). Proves that
under Ethereum's standard ">2/3 honest validators" assumption, a
transaction listed in a stored, non-equivocating inclusion list
cannot be excluded from a canonical block (modulo invalidity and
block fullness). Ships with both an abstract version of the
theorem and a fully concrete end-to-end version against a
nonce-only account-state model, with no opaque predicates
remaining. Build is green on Lean 4.29.1; the safety proofs are
sorry-free, and the five pure safety theorems depend on zero
kernel axioms.
curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh
lake buildThe toolchain is pinned by lean-toolchain; elan will fetch
the right Lean version automatically. There are no external Lean
dependencies.
End-to-end PoS-derived theorem against a concrete
EVM-validity model
(Focil.focil_concrete_pos_safety, in
Focil/EndToEnd.lean):
Fix any
StakeModelwith strictly more than 2/3 honest validators (the standard Ethereum PoS supermajority assumption), anyAttesterRunover that model whosecanAppendis pinned to a concrete account-state predicate, and aninitial : AccountStaterepresenting the genesis account state. For any blockband transactiontx: if some inclusion list stored inr.stateand not inr.state.equivocatorscontainstx, the block has accumulated a strict 2/3 quorum of votes,tx's nonce matches its sender's next-expected nonce inb's post-state, andbis not full, thentx ∈ b.transactions.
This is the marquee result of the project. No ForkChoice
postulates remain. No opaque predicates remain. The validity
predicate is the cheap nonce proxy described by EIP-7805 lead
author Thomas Thiery in his
Mar 16 2026 ethereum-magicians post
on FOCIL handshake Native Account Abstraction:
"This proxy is cheap... and works well for EOAs and EIP-7702."
The same module also exposes the builder-side contrapositive
Focil.focil_concrete_pos_censoring_block_not_canonical: a
block omitting a nonce-valid IL transaction cannot be the
canonical chain head.
The only remaining axioms-of-faith are Ethereum's standard
">2/3 honest" assumption (encoded as s.honest_majority) and
the spec's "honest attesters refuse non-compliant blocks" rule
(encoded as r.honest_rule).
End-to-end PoS-derived theorem (abstract validity)
(Focil.focil_pos_derived_safety, in
Focil/StakeModel.lean):
The same end-to-end claim against an abstract opaque validity predicate, for callers who do not wish to commit to the concrete account-state model. The concrete theorem is a specialization of this one.
Headline 1-of-N theorem (parameterised over validity)
(Focil.focil_one_of_n_protection,
in Focil/Safety.lean):
Fix any
ForkChoicevaluefc. For any blockband transactiontx: if some inclusion list infc.state.stored_ilswhose author is not infc.state.equivocatorscontainstx,txis appendable underfc.canAppend,bis not full, andbis canonical underfc, thentx ∈ b.transactions.
This is the formal counterpart of EIP-7805's marquee 1-of-N
honesty claim against an abstract ForkChoice: it suffices
that at least one non-equivocating IL committee member listed
tx. Adversaries controlling some committee seats and
equivocating others do not defeat the guarantee, as long as at
least one seat publishes a non-equivocating IL containing
tx. The end-to-end PoS-derived theorems above are corollaries
(instantiate fc with AttesterRun.toForkChoice).
Per-IL building block
(Focil.focil_censorship_resistance): same statement but takes
the witness IL as an explicit parameter. The 1-of-N theorem is
a thin existential-elimination corollary.
Builder-side contrapositive
(Focil.censoring_block_not_canonical): a block that omits an
"appendable, listed, non-equivocating, room-available"
transaction cannot become canonical. Useful as a builder-side
incentive statement.
Adversarial-validity attack, formalized
(Focil.front_running_breaks_appendability, in
Focil/AccountState.lean). One
specific way the CanAppend hypothesis can be defeated by an
adversary: a colluding party submits a transaction sharing an
IL transaction's sender; once the proposer appends it, the IL
transaction's nonce is stale and it is no longer appendable.
The theorem captures this attack at the level of the
appendability predicate, on a nonce-only account-state
realization. This is separate from the main safety theorem;
the main theorem still quantifies over arbitrary CanAppend.
What this companion theorem formalizes is one specific
realization of the threat model in FINDINGS.md §2.3.
The proof depends on:
- The validity predicate, parameterised by the safety chain
so that callers can plug in either an abstract opaque
predicate or a concrete EVM-validity model. The default
abstract predicate
CanAppend : Transaction → Block → Propis opaque; the concrete realizationFocil.canAppendToBlockis a nonce-only account-state model. The end-to-end concrete theorem is universally quantified over the choice ofinitial : AccountState. - The "honest attesters refuse non-compliant blocks" rule is
encoded as the
honest_rulefield ofAttesterRun. This is the per-attester rule EIP-7805 specifies as the normative behaviour of a correct validator. - The ">2/3 honest validators" assumption is encoded as the
honest_majorityfield ofStakeModel. This is the standard PoS safety assumption underlying every other Ethereum consensus result.
The repository ships four demonstrations:
Tests.Examples.emptyForkChoicedischarges the abstractForkChoiceobligations vacuously (sanity check only).Tests.Examples.threeValidatorForkChoiceis a hand-crafted 3-validator scenario; Scenarios 6–11 fire the headline theorem against it.Tests.Examples.attesterRun4vbuilds a 4-validatorStakeModelandAttesterRunfrom scratch and derives everything viaAttesterRun.toForkChoice. Scenario 12 firesfocil_pos_derived_safetyagainst it with noForkChoicepostulates remaining.Tests.Examples.attesterRun4vConcretepinscanAppendto the concrete account-state predicate. Scenario 14 firesfocil_concrete_pos_censoring_block_not_canonicalagainst it: every hypothesis is decidable on concrete data, no opaque predicate appears anywhere, and the conclusion (a block omitting a nonce-valid IL transaction cannot be canonical) is forced as a Lean kernel-checked consequence.
The architectural claim captured by the proof structure:
FOCIL censorship resistance is a structural consequence of
canonicality relative to a fork-choice rule that filters
non-compliant blocks. The proof of canonical_implies_compliant
walks the chain canonical → quorum → honest voter → compliance
directly. See docs/DESIGN.md for the full
architectural rationale.
This formalization is deliberately scoped. It does not model:
- A full EVM. The concrete EVM-validity layer covers per-sender nonces only (matching the EOA proxy described by EIP-7805's lead author). Balance-aware validity, EIP-7702 delegations, and EIP-8141 Frame Transactions are out of scope. See FINDINGS.md §2.3 and §4.3 for what this excludes.
- Liveness or progress. We prove non-canonicality of bad blocks but not the existence of good ones.
- IL gossip or the network layer. Network-level censorship attacks are captured only as preconditions of the theorem.
- Sequential validity dependence between IL transactions. The
EIP's §"Payload Construction" notes that IL transactions can
affect each other's validity; the Lean
CompliantWithpredicate quantifies per-transaction independently and does not capture this. See FINDINGS.md §2.5. - Equivocator detection.
state.equivocatorsis taken as input; the body ofon_inclusion_listis not modelled. See FINDINGS.md §2.6. - Proof-of-stake economics, slashing, or stake-weighted
voting. The fork choice's
HasQuorumis a binary predicate. - Cross-slot reasoning. The theorem applies to one block at one slot.
The full list with cross-references is in FINDINGS.md §6.
focil-lean4/
├── README.md # this file
├── LICENSE # CC0-1.0
├── FINDINGS.md # research log of spec issues + model limits
├── CONTRIBUTING.md # how to build, test, and contribute
├── THANKS.md # acknowledgments
├── CITATION.cff # citation metadata
├── lakefile.lean # Lake build manifest
├── lean-toolchain # pinned Lean toolchain version
├── FocilLean4.lean # library root, re-exports all modules
├── docs/
│ ├── DESIGN.md # architectural rationale
│ └── walkthrough.md # guided tour of the main theorem
├── Focil/
│ ├── Types.lean # data model: Transaction, IL, Block, FocilState
│ ├── Protocol.lean # CompliantWith, FocilCompliant
│ ├── ForkChoice.lean # ForkChoice structure + canonicality lemma
│ ├── Helpers.lean # small reusable lemmas
│ ├── Safety.lean # parameterised headline theorem and per-IL building block
│ ├── StakeModel.lean # PoS-derived ForkChoice; >2/3 honest assumption
│ ├── AccountState.lean # nonce-only EVM-validity model; FINDINGS §2.3
│ └── EndToEnd.lean # end-to-end safety against the concrete model
├── Tests/
│ └── Examples.lean # 14 worked scenarios; concrete ForkChoice instances
└── .github/
├── workflows/ci.yml # CI: build, type-check, axiom audit
└── ISSUE_TEMPLATE/ # issue and PR templates
For a reviewer encountering this repo for the first time, the suggested order:
docs/DESIGN.md: the architectural rationale: what we modelled, what we abstracted, why. Eight short sections; ten minutes.docs/walkthrough.md: a guided tour of the main theorem, line by line. What each hypothesis means in protocol terms; what the conclusion guarantees and what it doesn't.Focil/Types.lean: the data model. Each abstraction choice is justified inline.Focil/Protocol.lean: theCompliantWithandFocilCompliantpredicates. Cross-reference withvalidate_inclusion_listsinconsensus-specs/_features/eip7805/fork-choice.md.Focil/ForkChoice.lean: theForkChoicestructure (and its two propositional obligations) and the cornerstone lemmacanonical_implies_compliant.Focil/Safety.lean: the headline 1-of-N theorem and the per-IL building block. The proofs are short because the conceptual work happened in the previous files.Focil/StakeModel.lean: the PoS-derived layer. DefinesStakeModelandAttesterRun, proves the counting lemma, and suppliesAttesterRun.toForkChoiceplus the end-to-endfocil_pos_derived_safety.Focil/AccountState.lean: the nonce-only EVM-validity model. Formalizes the front-running attack from FINDINGS §2.3 as the theoremfront_running_breaks_appendability.Focil/EndToEnd.lean: the end-to-end concrete safety theorems.focil_concrete_safetydischarges the entire safety chain against the concrete account-state predicate; the PoS-derived corollaryfocil_concrete_pos_safetydoes the same starting from the >2/3 honest assumption. No opaque predicates remain.Tests/Examples.lean: fourteen concrete scenarios. Scenario 14 fires the concrete PoS-derived contrapositive on real account-state data; Scenario 12 fires the abstract PoS-derived theorem; Scenario 13 fires the front-running attack on concrete data; Scenario 11 fires the 1-of-N theorem on the abstractForkChoice; Scenarios 6–10 fire the per-IL building block, the contrapositive, and the equivocator degradation.FINDINGS.md: the research log; nine items spanning spec gaps, model limits, and the abstraction-level discoveries that emerged from building the formalization.
Lean's kernel can report which axioms a theorem depends on.
The four pure parameterised safety theorems in
Focil/Safety.lean and the end-to-end concrete safety
theorem Focil.focil_concrete_safety in Focil/EndToEnd.lean
all depend on zero kernel axioms (not even
Classical.choice or propext). The PoS-derived end-to-end
theorems in Focil/StakeModel.lean and the concrete
Focil/EndToEnd.lean PoS variant additionally depend on
propext and Quot.sound, two foundational kernel axioms
that ship with every Lean installation and are accepted
without controversy across the Lean community.
Classical.choice and sorryAx are not used anywhere in the
project.
To reproduce the audit, create a file with:
import FocilLean4
#print axioms Focil.focil_one_of_n_protection
#print axioms Focil.focil_censorship_resistance
#print axioms Focil.censoring_block_not_canonical
#print axioms Focil.canonical_implies_compliant
#print axioms Focil.AttesterRun.toForkChoice
#print axioms Focil.focil_pos_derived_safety
#print axioms Focil.front_running_breaks_appendability
#print axioms Focil.focil_concrete_safety
#print axioms Focil.focil_concrete_pos_safety
#print axioms Focil.focil_concrete_pos_censoring_block_not_canonicaland run:
lake env lean YourFile.leanYou should see:
'Focil.focil_one_of_n_protection' does not depend on any axioms
'Focil.focil_censorship_resistance' does not depend on any axioms
'Focil.censoring_block_not_canonical' does not depend on any axioms
'Focil.canonical_implies_compliant' does not depend on any axioms
'Focil.AttesterRun.toForkChoice' depends on axioms: [propext, Quot.sound]
'Focil.focil_pos_derived_safety' depends on axioms: [propext, Quot.sound]
'Focil.front_running_breaks_appendability' depends on axioms: [propext, Quot.sound]
'Focil.focil_concrete_safety' does not depend on any axioms
'Focil.focil_concrete_pos_safety' depends on axioms: [propext, Quot.sound]
'Focil.focil_concrete_pos_censoring_block_not_canonical' depends on axioms: [propext, Quot.sound]
CI runs this check on every push (see
.github/workflows/ci.yml) and
fails the build if Classical.choice or sorryAx is
introduced anywhere, or if any of the five pure safety
theorems acquires any axiom dependency.
Three of the items the formalization surfaced are substantive research observations; the rest are spec-hygiene issues and disclosed model limitations.
Substantive observations:
-
The honest-attester invariant in EIP-7805 admits two non-equivalent formal readings, and the natural one is unsatisfiable. The English-prose rule "honest attesters refuse to vote for non-compliant blocks" can be read globally (across all stores) or locally (against the attester's own store). The global reading cannot be discharged non-vacuously when EVM validity is opaque. The spec is correct under the local reading; informal arguments that compose the rule across attesters with different stores have a hidden quantifier-scope assumption. (§2.7)
-
Equivocation is a free censorship channel for any transaction listed by only one IL committee member. A Byzantine member can void their own contribution by signing two distinct ILs. The EIP's existing equivocation handling is correct fork-choice safety, but it degrades the "1-of-N honesty" guarantee to "1-of-(N − equivocators)" for any transaction listed only by an equivocating member. The EIP addresses equivocation at the bandwidth level only. Demonstrated by example in
Tests/Examples.leanScenarios 9–10. (§2.4) -
Adversarial validity changes are formally exhibited. A colluding party sharing an IL transaction's sender can submit a transaction that, once appended by the proposer, makes the IL transaction non-appendable. Formalized as
front_running_breaks_appendabilityinFocil/AccountState.lean, with Scenario 13 demonstrating the attack on concrete data. The attacker pays one gas fee with no slashing penalty. (§2.3)
Spec-hygiene issues:
MAX_TRANSACTIONS_PER_INCLUSION_LIST = 1is marked# TODO: Placeholderinbeacon-chain.mdand contradicts the 8 KiB per-IL byte cap quoted by the EIP body. (§1.3)validate_inclusion_listshas no body: only a one-sentence docstring that leaves three substantive questions open. (§2.1)parent_hash/parent_rootreferenced invalidator.mdare not fields of theInclusionListcontainer inbeacon-chain.md. (§1.2)
Disclosed model limitations:
- Sequential dependence between IL transactions is not
captured by
CompliantWith(§2.5). - Equivocator detection is not modelled;
state.equivocatorsis taken as input (§2.6).
Plus smaller cross-references and threat-model notes; see FINDINGS.md for the full discussion.
FOCIL (Fork-Choice enforced Inclusion Lists, EIP-7805) is a committee-based mechanism for guaranteeing transaction inclusion in Ethereum. A small committee of validators per slot publishes inclusion lists; the next block's proposer must include those transactions or have their block orphaned by attesters via the fork-choice rule. The mechanism's claimed property is "1-out-of-N" honesty among committee members.
FOCIL is the headline feature of Ethereum's late-2026 Hegotá hard fork, scheduled to follow Glamsterdam. Vitalik Buterin's A shallow dive into formal verification (May 18, 2026) sharpened the case for taking machine-checked proofs of consensus-layer mechanisms seriously, and was a direct motivation for this work.
References:
- EIP-7805: primary spec.
- consensus-specs
_features/eip7805/: Python reference implementation, pinned at commite678deb772fe83edd1ea54cb6d2c1e4b1e45cec6. The directory has since been promoted out of_features/and now lives atspecs/heze/on the default branch; the pinned commit is what this repository's citations refer to. - Ethereum Magicians: EIP-7805 discussion.
- ethresear.ch: original FOCIL proposal.
The end-to-end concrete safety theorems
(Focil/EndToEnd.lean) discharge the headline 1-of-N claim
against a nonce-only account-state model with no opaque
predicates remaining. The natural next milestones extend the
concrete EVM-validity layer to cover more of EIP-7805's threat
surface.
Active milestone, balance-aware concrete validity. The current concrete model tracks per-sender nonces only. A balance-aware variant would let us formalize the balance-drain attack from FINDINGS §2.3 (a colluding party drains a sender's balance below the base fee, invalidating the IL transaction) end-to-end against the same PoS-derived chain. Structurally identical to the nonce model; the case surface roughly doubles. This directly addresses FINDINGS.md §4.3.
Active milestone, refined CompliantWith capturing
sequential validity dependence between IL transactions. The
current CompliantWith predicate quantifies per-transaction
independently against the final block, but EIP-7805
§"Payload Construction" notes that an IL transaction can
become valid because an earlier IL transaction was appended.
A refined predicate would thread a hypothetical post-state
through the appendability check. This directly addresses
FINDINGS.md §2.5.
Other contribution opportunities, ordered by leverage:
- EIP-8141 Frame Transactions and the bounded validation-prefix replay rule. EIP-7805's lead author describes a refinement of the FOCIL omission check for native AA transactions in his Mar 16 ethereum-magicians post. Formalizing the bounded-VERIFY-execution check and the per-IL VERIFY-gas budget would extend the concrete safety chain to cover EIP-8141 Frame Transactions.
- Equivocator-detection model. Formalize
on_inclusion_listand prove that a faithful execution correctly populatesstate.equivocators. (FINDINGS.md §2.6) - IL gossip / network model. Formalize the threat surface for network-level adversaries. (FINDINGS.md §2.2)
See CONTRIBUTING.md for how to build, test,
and submit changes, and THANKS.md for
acknowledgments.
CC0-1.0, matching the EIPs. Use freely.