Changes Merged Over Time and Why
Day 0 Fixes — January 29, 2026
Why this mattered: two tiny fixes merged on the same day as the original submission, establishing a fast-review cadence that carried through the rest of the spec's evolution.
PR #11205: Add missing elision of VERIFY frame data from signature hash
Author: fjl | Merged: Jan 29
- Bug: the original spec did not elide
frame.dataof VERIFY frames when computing the canonical signature hash - This was critical because VERIFY frames contain the signature itself; by definition it cannot be part of the signature hash
- Merged same day
PR #11209: Fix status field number
Author: kevaundray | Merged: Jan 29
- The TXPARAM table had an incorrect field number for the
statusparameter - Simple numbering fix, approved by fjl
APPROVE Relaxation — February 10, 2026
Why this mattered: unblocked proxy-based smart accounts (Safe-style) from adopting the spec. Without this, accounts whose outer proxy predates APPROVE would have been locked out entirely.
PR #11297: Relax requirement that APPROVE must be called by top level call frame
Author: lightclient | Merged: Feb 10
- Why: Existing smart accounts (especially proxy-based ones like Safe) can change their implementation code but NOT their outer proxy contract. The outer proxy uses
RETURN, notAPPROVE. Requiring top-levelAPPROVEmade adoption impossible for these accounts. - Change:
APPROVEbecame transaction-scoped, meaning it can be called from any depth and updatessender_approved/payer_approveddirectly, rather than requiring the top-level frame to exit with a special return code.
From lightclient's PR description:
This allows existing smart accounts to more easily adopt EIP-8141. Before, the requirement was that accounts must exit the top level frame with APPROVE. Since APPROVE only exists with 8141, not smart accounts today support it. More importantly, smart accounts who are deployed with proxies can change their smart account implementations, but still not the outer proxy which won't understand
APPROVE.
Bug Fixes & Clarifications — February-March 2026
Why this mattered: caught a refactor-introduced CALLER/ADDRESS bug in APPROVE and settled ambiguities around frame reverts before downstream PRs built on the older, wrong assumptions.
PR #11344: Fix some issues with EIP-8141
Author: derekchiang | Merged: Mar 2
- Fixed CALLER vs ADDRESS: Changed
CALLER == frame.targettoADDRESS == frame.targetfor APPROVE. In VERIFY frames, CALLER is ENTRY_POINT, not frame.target. This was a bug introduced during refactoring. - Removed APPROVE restriction to VERIFY frames: lightclient wanted APPROVE available in any mode for private pool use cases (stateful approvals).
- Clarified frame reverts: Made explicit that a frame revert discards that frame's state changes but doesn't affect other frames.
- Notable discussion: nlordell asked about the TXPARAM numbering jump from 0x09 to 0x10; lightclient confirmed it was intentional to separate tx-level vs frame-level queries.
EOA Support — March 5-10, 2026
Why this mattered: the pivot. Made EOAs first-class users of frame transactions and reframed the spec from "smart-account-assumed" to "EOA-first." Every downstream design decision traces back to this merge.
PR #11379: Add EOA support
Author: derekchiang | Merged: Mar 10
- Why: The biggest driver was adoption: if most users are on EOAs, frame transactions need to work for them natively, without requiring smart contract deployment.
- What changed: Added "default code" behavior for EOAs:
- In VERIFY mode: reads
frame.dataas a signature, supports SECP256K1 (0x0) and P256 (0x1) types, callsAPPROVE(scope) - In SENDER mode: reads
frame.dataas RLP-encoded calls[[target, value, data], ...]and executes them - In DEFAULT mode: reverts
- In VERIFY mode: reads
- Also initially added a
valuefield to frames (later removed; the default code handles value via call encoding)
Opcode Redesign — March 12, 2026
Why this mattered: gave scalar and variable-length transaction data the opcodes they actually need. Scalar values no longer pay the cost of copy semantics meant for byte strings, and frame input data gets dedicated FRAMEDATA* opcodes that match its shape.
PR #11400: Clean up frame access opcodes
Author: fjl | Merged: Mar 12
- Why: Most TXPARAM values are 32 bytes or less, so
TXPARAMSIZE/TXPARAMCOPY(designed for variable-length data) were unnecessary for most fields. The only variable-size data is frame input data. - Change: Replaced
TXPARAMSIZE (0xb1)andTXPARAMCOPY (0xb2)with dedicatedFRAMEDATALOAD (0xb1)andFRAMEDATACOPY (0xb2). RenamedTXPARAMLOADto justTXPARAM (0xb0).
From fjl's PR description:
Most values returned by the TXPARAM opcode family is 32-bytes or less, so it makes no sense to be able to copy the data into memory. The only variable-size components of the transaction are the frame list and the input data of each frame. So I am defining specialized opcodes for reading the input data of the frame.
Approval Bits — March 12-13, 2026
Why this mattered: let users sign over their intended approval scope as part of the signed transaction payload, so smart accounts don't each have to implement bespoke scope-extraction logic. Simplified the default code and moved trust about scope from frame data to mode bits.
PR #11401: Add approval bits to frame mode
Author: fjl | Merged: Mar 12
- Why: Users needed a way to specify their intended approval scope in the signed transaction data so that smart accounts don't have to extract scope from
frame.data(which is elided from the signature hash). Without this, accounts would need to computekeccak(sighash | scope), which is repetitive logic every account must implement. - Change: Added bits 9-10 of
frame.modeas approval scope constraints. These constrain whichAPPROVEscopes are valid for that frame. - Also shifted APPROVE scope values from 0-indexed (0x0, 0x1, 0x2) to 1-indexed (0x1, 0x2, 0x3) so that the mode bits can directly encode the constraint.
From fjl's PR description:
The primary motivation for adding these bits is allowing the user to specify to their own account what should be approved, while retaining the ability to sign directly over the sighash of the transaction. However, the concept of mode bits is going to be useful for other things we may have to put in later, and it also gives some security benefits.
PR #11402: Fix bit indices
Author: fjl | Merged: Mar 13
- Changed from 0-indexed to 1-indexed bit numbering (bits 9 and 10 instead of 8 and 9), since bits are "typically one-indexed."
Atomic Batching — March 11-25, 2026
Why this mattered: settled a month-long debate (atomic-by-default vs opt-in vs group-id) with a flag-based design that gave users atomic "approve + swap" semantics without breaking paymaster flows that need non-atomic defaults.
PR #11395: Add support for atomic batching
Author: derekchiang | Merged: Mar 25
- Why: Users need "all-or-nothing" semantics for related operations (e.g., ERC-20 approve + swap). Without this, a revert in one frame leaves prior frames' state changes applied, creating dangerous intermediate states.
- Evolution: Originally proposed a
SENDER_ATOMICmode. After extensive discussion:- pedrouid argued for atomic-by-default
- derekchiang & frangio explained non-atomic is needed for paymasters
- 0xrcinus proposed explicit group IDs
- sm-stack suggested bit flags
- Final design: Bit 11 of
frame.modeas the "atomic batch" flag. Consecutive SENDER frames with the flag set form a batch. If any frame in the batch reverts, all preceding frames are reverted and remaining frames are skipped. - Additional change: Required
sender_approvedto be true before any SENDER frame can execute. This forbids APPROVE from being called in SENDER mode, preventing complexity where an atomic batch could revert a payment approval.
From derekchiang's PR description:
This PR also adds the explicit requirement that
SENDERframes can only be executed whensender_approvedandpayer_approvedhave been set totrue, which essentially forbidsapprovefrom being called inSENDERmodes. This is important because otherwise aSENDER_ATOMICframe canapprovegas payment, and then the payment frame may be reverted by otherSENDER_ATOMICframes, creating complexity for transaction validation.
Mempool Policy — March 16-25, 2026
Why this mattered: turned EIP-8141 from a consensus-layer spec into something clients could actually ship. Bounded validation cost, standardized the paymaster shape, and replaced ERC-7562's reputation/staking complexity with a canonical-paymaster code match.
PR #11415: Add mempool policy
Author: lightclient | Merged: Mar 25
- Why: Without clear mempool rules, node operators would each implement their own policies, creating inconsistency and potentially enabling DoS attacks. The policy section was inspired by ERC-7562 but simplified.
- Key innovations:
- Validation prefix: Only the frames up to
payer_approved = trueare subject to mempool rules. Post-payment frames are arbitrary. - Canonical paymaster: A standardized paymaster contract verified by runtime code match. Removes the entire reputation/staking system from ERC-7562.
- Non-canonical paymaster limit: At most 1 pending tx per non-canonical paymaster
- Banned opcodes: ORIGIN, GASPRICE, BLOCKHASH, COINBASE, TIMESTAMP, NUMBER, PREVRANDAO, GASLIMIT, BASEFEE, BLOBHASH, BLOBBASEFEE, GAS (with exceptions), CREATE, CREATE2 (with exceptions), INVALID, SELFDESTRUCT, BALANCE, SELFBALANCE, SSTORE, TLOAD, TSTORE
- MAX_VERIFY_GAS: 100,000 gas cap for validation prefix
- Four recognized validation prefixes: self-relay (basic & deploy), canonical paymaster (basic & deploy)
- Validation prefix: Only the frames up to
- Notable review feedback: jochem-brouwer provided detailed review of the canonical paymaster Solidity contract, catching PUSH0 optimization, stack order documentation, withdrawal overwrite handling, and chain ID checks.
From lightclient's PR description:
One important change vs. 7562 is relying on a canonical paymaster contract. This point is open for discussion generally, but by having a canonical contract, we can remove the complex reputation system around the staking. It's also possible to add more functionality here over time.
Default Code Update — March 26, 2026
Why this mattered: kept the reference implementation in sync after approval bits changed how scope is encoded. Without this, every implementer would have had to reconcile an outdated default code against the latest approval-bit semantics on their own.
PR #11448: Update default code to match latest spec
Author: derekchiang | Merged: Mar 26
- Why: The approval bits addition meant the default code could be simplified: the scope is now read from the mode bits instead of being encoded separately.
- Updated the default code Python reference implementation to match all recent spec changes.
Header Metadata Fix — April 8, 2026
Why this mattered: a simple dependency-header fix that had been open for two months. The merge is notable mostly for how uncontroversial it was, and how long such a trivial change can sit waiting for author attention.
PR #11251: Add EIP-1559 to requires header
Author: BonyHanter83 | Merged: Apr 8 (opened Feb 4)
- Why: The spec uses EIP-1559's
max_priority_fee_per_gasandmax_fee_per_gasfields and explicitly states thateffective_gas_priceis calculated per EIP-1559, but the header didn't list it as a dependency. - Change: Added
1559to therequiresheader field alongside2718and4844. - Approved by lightclient.
- This PR was open for over two months before being merged. It was a simple metadata fix that had no controversy.
Broad Spec Tightening — April 14, 2026
Why this mattered: the broadest single-PR restructuring since approval bits. Introduced a fifth opcode (FRAMEPARAM), hardened both default-code signature paths, reduced MAX_FRAMES, and locked deterministic deployment to EIP-7997. Consolidated several open threads into one coherent update.
PR #11521: Tighten spec
Author: benaadams (Ben Adams) | Merged: Apr 14
A 295-line spec-hardening PR consolidating several open threads. Changes:
- Frame model: Split the packed
modefield into separatemode+flagsfields. AddedFRAMEPARAM (0xb3)opcode for frame introspection (renamed fromFRAMEINFOat derekchiang's suggestion for consistency withTXPARAM). Introduced explicitresolved_targetused consistently throughout execution. - APPROVE/VERIFY semantics: Defined approval scopes as a bitmask with double-approval prevention. Aligned public-mempool prefixes. Made the VERIFY/STATICCALL carve-out explicit. Clarified that payment scopes collect
TXPARAM(0x06). Allowed third-party EOA paymasters in the default-code path. - Default code hardening: Low-
senforcement for secp256k1. Reject failedecrecover. Added P256 address-domain separation (0x04prefix beforeqx|qy). RequireP256VERIFYto reject invalid public keys. - Limits and accounting: Reduced
MAX_FRAMESfrom10^3to64. AddedFRAME_TX_PER_FRAME_COST(475 gas). Bounded frame gas totals. Clarified gas semantics forFRAMEDATACOPYandTXPARAM/blob access. - Deployment: Locked deterministic deployment to EIP-7997. Made EIP-7702 interaction explicit. Added EIP-7997 to the
requiresheader. - Security notes: Stronger warnings around VERIFY-data malleability,
DELEGATECALL+APPROVE, deploy-frame front-running, explicit-sender state-read amplification, and validation-time cross-frame data visibility. - Canonical paymaster: Updated to use
TXPARAM(0x08). Documented that the current canonical implementation is single-signer secp256k1 only.
Key review discussion: fjl questioned lowering MAX_FRAMES from 1000 to 64, noting the high limit was intentional for native batching/bundling. benaadams responded that journaling carries across frames, creating up to 2000 effective call depth, and that it's easier to increase later after empirical measurement than to decrease. lightclient and derekchiang both approved.
This is the broadest restructuring since PR #11401 (approval bits) and the first PR to add a fifth opcode to the spec.
Per-Frame Value — April 16, 2026
Why this mattered: resolved the longest-running ergonomic ask. Wallets can now build a simple ETH transfer as one SENDER frame with target = destination, value = amount, instead of encoding an RLP call list inside default code. Ended the "frames are dumb message pipes" criticism from wallet developers.
PR #11534: Add value field to frame
Author: lightclient | Merged: Apr 16
Resolves the long-running community request for native ETH value transfer in frame transactions. Changes:
- Frame model: Extended the frame tuple from
[mode, flags, target, gas_limit, data]to[mode, flags, target, gas_limit, value, data]. Thevaluefield is interpreted as the top-level call value in wei. - Validity rules: Added
frame.value < 2**256andframe.mode == SENDER or frame.value == 0. Non-zerovalueis only valid inSENDERframes;DEFAULTandVERIFYframes must setvalue = 0. - Execution semantics: In the top-level frame call,
CALLVALUE = frame.value. If the caller lacks sufficient balance to transferframe.value, the frame reverts (ordinary CALL value-transfer semantics).ENTRY_POINTis now documented as observingCALLVALUE = 0for DEFAULT/VERIFY frames. - FRAMEPARAM extension: Added
FRAMEPARAM(0x08, frameIndex)returning the frame'svalue. - TXPARAM clarification:
TXPARAM(0x06)(max gas and blob fees) explicitly does not include anyframe.valuetransfers. - Default code change: In
SENDERmode whenresolved_target != tx.sender, the default code now returns successfully with empty data instead of reverting, because the top-levelframe.valuetransfer has already been applied by the frame call. This matches the behavior of calling an empty-code account. - Signature hash coverage: Documented that non-
VERIFYframe metadata, including aSENDERframe'svalue, remains covered by the canonical signature hash. - Gas accounting: Any
frame.valuetransferred by aSENDERframe is separate fromtx_feeand follows ordinary CALL value-transfer gas semantics. - Rationale: Renamed the "No value in frame" rationale section to "Per-frame value" and explained that restricting non-zero
valuetoSENDERframes keepsVERIFYandDEFAULTside-effect-free with respect to ETH transfers, preserves theSTATICCALL-like behavior ofVERIFY, and avoids requiringENTRY_POINTto fund top-level ETH transfers. - Examples: All transaction examples updated with a
Valuecolumn. Example 1a (Simple ETH transfer) was restructured: instead of instructing the sender account to send ETH via payload decoding, theSENDERframe now setstarget = destinationandvalue = amountdirectly.
Key review discussion: lightclient's PR description notes the original resistance to a value field (preferring user-operation execution to be handled by the account) and the reversal now that frames are targeted at a good out-of-the-box experience without requiring wallet-side batching. Auto-merged after all reviewers approved; no debate on the merged PR.
Context: this resolves the "VALUE in SENDER frames" pending proposal that had accumulated support from rmeissner (Safe), DanielVF, frangio, 0xrcinus, derek, and matt across posts #124-134.
Sighash Type Prefix — April 22, 2026
Why this mattered: aligned EIP-8141's canonical sighash with the EIP-2718 typed-transaction convention, closing a cross-type signature replay vector.
PR #11544: Mix in transaction type to the sighash
Author: derekchiang | Merged: Apr 22
One-line change in compute_sig_hash:
- Replaced
keccak(rlp(tx_copy))withkeccak(bytes([FRAME_TX_TYPE]) + rlp(tx_copy)). - Prefixes the type byte (
FRAME_TX_TYPE = 0x06) before RLP-encoding, matching the EIP-2718 convention used by every other typed transaction type since EIP-1559. - Without the prefix, a signature over a frame-transaction sighash could in theory be reused against another transaction type sharing the same RLP body.
All reviewers approved by Apr 18; auto-merged on Apr 22 with no further debate.
Active/Open PRs
As of April 24, 2026. These PRs represent active design proposals that may change the spec in the near future.
PR #11272: Disable EIP-3607 check for frame transactions (open since Feb 6)
Author: Thegaram
- Why: EIP-3607 rejects transactions from senders with deployed code, which would block frame transactions for smart accounts.
- Still open. lightclient's earlier review was dismissed on Apr 8, and the PR remains unresolved.
PR #11481: Add signatures list to outer tx (open since Apr 2)
Author: lightclient
- Why: Forward-compatibility with PQ signature aggregation. PQ signatures are large, and aggregating them will be critical.
- Proposed change: Add a new
signaturesfield to the outer transaction object, containing signature objects with algorithm metadata, message, and signer. Signatures are verified before frame execution. - Significance: This is the most structurally significant open proposal; it would change the transaction format itself. In the future, block-level aggregated witnesses could elide individual signatures.
- All reviewers approved, but derekchiang raised a practical concern (Apr 9): smart contracts leveraging outer signatures don't know which index their signature is at. The contract can't hardcode an index because the transaction may have any number of signatures in arbitrary order, so the default code has to loop through the entire list to find the relevant entry. This is an ergonomic and gas-efficiency weakness that needs addressing.
From lightclient's PR description:
Any important goal of 8141 is to be forward compatible with signature aggregation techniques, especially with respect to PQ signatures. As those signatures are quite large, aggregating them may become very important as many users begin migrating.
PR #11482: Allow using precompiles for VERIFY frames (open since Apr 2)
Author: derekchiang
- Why: Allow both EOAs and contract accounts to use precompiles for verification, enabling key rotation and shared verification logic.
- Proposed change: Designate "signature precompiles" that VERIFY frames can target natively. The precompile reads the public key commitment from storage.
- All reviewers approved (as of April 14), awaiting merge. May need rebasing after PR #11521 (Apr 14) and PR #11534 (Apr 16).
From derekchiang's PR description:
This will allow a contract account to use precompiles for verification, while still having code that serves other purpose (e.g. for execution). As a side benefit, this also enables key rotation, since the precompile reads the public key commitment from storage.
PR #11488: Fix spec inconsistencies (open since Apr 6)
Author: chiranjeev13
- Proposed changes:
- Add static VERIFY frame count check (
<= 2) to constraints, sincesender_approvedandpayer_approvedare one-shot flags - Fix stale APPROVE scope values in structural rules:
self_verify→APPROVE(0x3),only_verify→APPROVE(0x2),pay→APPROVE(0x1) - Remove
frame.target != tx.sendercheck from default VERIFY code to allow any EOA as paymaster
- Add static VERIFY frame count check (
- Inspired by node.cm's observations on the EthMagicians thread (posts #135-136)
- Some of these fixes overlap with changes already merged in PR #11521
- No reviews yet from core authors
PR #11537: Add EIP-8141 to CFI in EIP-8081 Hegotá meta EIP (open since Apr 17)
Author: dionysuzx
- Why: Adds EIP-8141 to the
Considered for Inclusionlist in the Hegotá fork meta EIP (EIP-8081), formalizing the CFI status that had been assumed based on strawmap and ACDE discussions. - Proposed change: 3 lines in
EIPS/eip-8081.mdadding EIP-8141 under CFI, plus EIP-7716 and EIP-8205 under PFI. - Rationale links: decisions captured at ACDE #233 timestamp 5871s (forkcast) and ACDC #177 timestamps 3532s and 3853s.
- Still needs one more reviewer from @ralexstokes or @timbeiko. This is a fork-inclusion governance milestone, not a spec change.
PR #11555: Add support for guarantors (open since Apr 22)
Author: derekchiang
- Why: Provides a public-mempool path for transactions whose sender VERIFY logic reads shared state (ERC-20 balances, environmental opcodes), which otherwise violates the restrictive tier's
storage reads only on tx.senderrule. - Proposed change: Introduce a "guarantor" payer that pays for the transaction even if sender validation fails. When a guarantor is present, mempool nodes may skip sender-validation simulation entirely and propagate the transaction on the strength of the guarantor's signature alone.
- Consequence: a transaction with a guarantor can use any sender validation logic (including shared-state reads and environmental opcodes) and still propagate through the public mempool. This opens a third path for ERC-20 gas repayment alongside live (offchain) and permissionless (onchain) paymasters.
- Status: Early proposal; Derek's description notes the authors are still iterating on the idea.
From derekchiang's PR description:
The idea is to introduce the concept of a "guarantor," which is a payer that pays for the transaction even if sender validation fails. As long as a transaction has a guarantor, mempool nodes do not need to check if the sender validation succeeds, and can skip simulation for sender validation altogether. As a result, transactions with a guarantor can use any sender validation logic, including access to shared state, environmental opcodes, etc., and still safely pass through the public mempool.
PR #11567: Relax mempool rules to not require a specific factory (open since Apr 24)
Author: derekchiang
- Why: The current spec hard-codes the EIP-7997 deterministic factory predeploy as the only valid target for a
deployframe under mempool rules. This couples EIP-8141 to a specific factory contract and blocks senders who want cross-chain-stable addresses through alternative factories, custom CREATE2 deployers, or direct EIP-7702 delegation installation. - Proposed change: Drop EIP-7997 from
requires. Rewrite the mempool deploy-frame rule so that any contract may beframe.target, provided the frame's execution satisfies the validation trace rules. The write policy expands from "deterministic deployment through a known deployer" to "(a)CREATE,CREATE2, orSETDELEGATEoperations that install code attx.sender, or (b)SSTOREs totx.sender's storage."CREATE(0xF0) andSETDELEGATE(0xF6) joinCREATE2(0xF5) in the list of opcodes allowed inside the firstdeployframe. Resulting code may be either conventional contract code or an EIP-7702 delegation indicator. - Consequence: EIP-7997 becomes the canonical but non-mandatory path. A factory is admissible as long as it is stateless in the validation-trace sense (no reads of mutable state outside
tx.sender, no per-deploy factory storage such as counters or reentrancy flags). This unifies smart-account deployment and EIP-7702 delegation installation under the same deploy-frame primitive. - Status: Draft as of Apr 24. No reviews yet.
Rejected/Closed PRs
PR #11404: Simplify approval bits (closed Mar 26)
Author: derekchiang
- Proposed an alternative approach to approval bit handling
- Superseded by the mode flags approach (PR #11401)
- Sparked useful discussion: 0xrcinus questioned whether bits were needed at all, Meyanis95 reviewed edge cases
PR #11408: Migrate EOA default code to EIP-7932 registry (closed Mar 21)
Author: SirSpudlington
- Proposed using EIP-7932's signature registry for default code, citing P256 malleability fixes
- lightclient rejected: "We want to reserve the ability to define custom behavior in 8141 default contract and we don't want to rely on another EIP/precompile like this."
PR #11455: Small tweaks to default code for EIP-7392 compatibility (closed Apr 23)
Author: SirSpudlington
- Spiritual successor to the closed PR #11408. No dependency introduced; just aligned default-code values with EIP-7392 for interoperability.
- Never gathered the required reviewer approvals from core authors. Closed without merge after ~4 weeks open.
PRs #11310, #11314, #11321: Fix broken links (all closed)
Author: marukai67
- Three separate PRs attempting to fix allegedly broken links in the spec (to ERC-7562, EIP-2718, and other references)
- All rejected by lightclient with variants of "It's not broken" / "Not broken, thanks though"
- The links use relative paths that work in the EIPs rendering system but may look broken locally