Skip to content

What EIP-8141 Can Do Today and How It Works ​


About this page ​

This is the primary reference for what EIP-8141 does today and how a frame transaction actually flows through the protocol. It's for readers who want the mechanism in detail: what a transaction looks like on the wire, what the EVM does with it, and what the mempool will and won't propagate.

Background assumed: comfortable reading an EIP, know what ECDSA and EOAs are. No prior exposure to ERC-4337, EIP-7702, or FOCIL needed; those are introduced where they come up.

Transaction Lifecycle ​

A frame transaction arrives at a node and goes through four conceptual stages:

  1. Admission. The node checks whether the transaction matches a shape the public mempool will propagate. The mempool only admits transactions whose validation prefix (the opening frames up to the point a payer is approved) fits one of four recognized patterns, stays under a gas cap, and reads only predictable state. If it doesn't fit, the transaction is still consensus-valid on-chain but has to reach a block builder through a private channel.
  2. Validation. The protocol runs the opening frames. These are the frames whose job is to prove "this transaction is authorized and someone is paying for it." Approval-bearing validation frames call the APPROVE opcode before returning; expiry-verifier frames are the special timestamp-check exception. This is where signature checks, policy checks, and paymaster logic live.
  3. Execution. Once a sender has been approved and a payer has been approved, the protocol runs the remaining frames as normal EVM calls. These are the frames that actually do what the user wanted: a token transfer, a swap, a contract deployment. Multiple execution frames can be grouped into an atomic batch so they all-or-none revert together.
  4. Settlement. After the last frame runs, the protocol computes gas used, refunds the payer, and writes per-frame receipt entries. The transaction receipt records which address paid, which frames succeeded, and the logs each frame produced.

The rest of this page is the mechanical detail behind these four stages.

Core Concept ​

EIP-8141 introduces Frame Transactions, a new transaction type (0x06) where a transaction consists of multiple frames, each with a purpose (verify identity, execute calls, deploy contracts). The protocol uses frame modes to reason about what each frame does, enabling safe mempool relay and flexible user-defined validation.

EIP-8141 is Scheduled for Inclusion (SFI) in the Hegotá upgrade (PR #12251, merged Aug 27 after ACDE #244), with the recorded caveat that AA will ship in Hegotá but the specific implementation, including the EIP number, may still change.

A key insight for understanding the current spec: EIP-8141 is two specs in one.

  • The execution model says "validation and payment are programmable": any account code can verify any signature scheme and approve any payer, with arbitrary logic.
  • The mempool model says "that programmability is only publicly relayable when it fits a small set of validation-prefix shapes and state-dependency rules."

The execution model defines what is possible; the mempool model defines what is propagatable. A frame transaction that doesn't match the mempool rules is still valid on-chain; it just can't be gossiped through the public p2p network and must reach a block builder through private channels.

Transaction Structure ​

[chain_id, nonce, sender, frames, signatures, fees, blob_versioned_hashes]

frames = [[mode, flags, target, limits, value, data], ...]
limits = [execution, state]
signatures = [[scheme, signer, msg, signature], ...]
fees = [max_priority_fee_per_gas, max_fee_per_gas, max_fee_per_blob_gas]
  • sender: the 20-byte address of the account originating the transaction
  • Each frame has a mode (lower 8 bits only), a flags field (approval scope + atomic batch), a target address (or null for sender), independent execution and state-gas limits, a value field (ETH to transfer in the top-level frame call, non-zero only in SENDER frames), and arbitrary data
  • signatures is a list of signature objects on the outer transaction, verified before any frame executes for protocol-validated schemes. During execution, signer identity and signature validity are already established for SECP256K1 and P256; custom schemes carry witness bytes as ARBITRARY signatures and validate them in account code.
  • Up to 64 frames per transaction
  • The three fee fields must fit in 256 bits (PR #12005, merged Jul 23). Blob hashes must be 32-byte KZG versioned hashes; max_fee_per_blob_gas must be zero when no blobs are attached.

Signature schemes:

SchemeNameProtocol validationGas
0x0ARBITRARYNo cryptographic validation by the protocol; signer must be empty. Length is available through SIGPARAM; raw bytes are copied through SIGDATACOPY.100
0x1SECP256K165-byte `v
0x2P256`r

SIGPARAM (0xb4) exposes signature metadata and the byte length of an ARBITRARY witness. SIGDATACOPY (0xb5) copies an ARBITRARY entry's raw witness bytes into memory. Protocol-validated signature bytes remain opaque, preserving future aggregation. PR #12187 (merged Aug 18) split copying into its own opcode so SIGPARAM always has a static two-item stack input. PR #12469 (merged Oct 9) named every introspection parameter (TXPARAM_*, FRAMEPARAM_*, SIGPARAM_*) without changing values.

Sibling EIP-8397 (merged Oct 14) adds a fourth scheme, AUTHENTICATOR (0x3): the signer is an authenticator contract, the protocol runs authenticate(digest, proof) in a state-independent context with a fixed 50,000-gas budget (52,600 per entry), and SIGPARAM(0x04) exposes the authenticated key_id.

Frame-data access has explicit stack order: FRAMEDATALOAD pops offset from the top and frameIndex next; FRAMEDATACOPY pops memOffset, dataOffset, length, then frameIndex. PR #11938 (merged Jul 17) pinned these previously implicit operand orders for client interoperability.

Frame Modes ​

ModeNameBehavior
0DEFAULTCalled from ENTRY_POINT. Used for deployment or post-op tasks.
1VERIFYRead-only (STATICCALL semantics). Approval-bearing validation shapes must call APPROVE; expiry-verifier frames are the timestamp-check exception. Used for authentication & payment authorization.
2SENDERCalled from tx.sender. Requires prior sender_approved. Executes user's intended operations.

These are the only valid modes in EIP-8141 itself. PR #12453 (merged Oct 7) replaced the numeric bound mode < 3 with set membership, mode in (DEFAULT, VERIFY, SENDER); an EIP that extends frame transactions adds its own value to the set. Current sibling assignments: ASSERT = 3 (EIP-7906 outcome assertions), DEP_VERIFY = 4 (EIP-8288 aggregated dependencies), and COMMIT = 5 / REVEAL = 6 (EIP-8209 commit-reveal). There is no central registry; PR #12253 proposing one closed Oct 8.

Flags (separate field, introduced by PR #11521):

  • Bits 0-1: Approval scope constraint (limits which APPROVE scope can be used)
  • Bit 2: Atomic batch flag, valid only on DEFAULT and SENDER. A flagged frame must be followed by another non-VERIFY frame, so no VERIFY frame can be inside or terminate a batch. Every frame belonging to a batch, including its unflagged terminating frame, must have approval-scope bits set to zero.

The APPROVE Mechanism ​

APPROVE (0xaa) is the central innovation. It's an opcode that:

  1. Terminates the current frame successfully (like RETURN)
  2. Updates transaction-scoped approval variables

Stack: [offset, length, scope] (with double-approval prevention: once a scope bit is set, it cannot be set again)

Scopes:

  • 0x1: Approve payment — increments the sender nonce, collects the transaction's maximum cost, and sets payer to the resolved target
  • 0x2: Approve execution — sets sender_approved = true (only valid when frame.target == tx.sender)
  • 0x3: Approve both execution and payment

Security: Only the resolved frame target can call APPROVE (ADDRESS == resolved_target check). APPROVE exceptional-halts outside frame-transaction execution. The requested scope must be non-zero and must fit the frame's allowed scope bits. sender_approved must be true before payment-only approval can set the payer. A failed precondition reverts only the current EVM call frame, not the whole 8141 frame (PR #12212, merged Aug 20).

Journaling: payer and sender_approved are journaled like state. If a call that executed APPROVE later reverts, the approval context rolls back with the nonce increment and max_cost collection (PR #12458, merged Oct 8). Before this fix a reverted nested approval could leave payer set, refunding ETH that was never collected.

Gas: APPROVE has no execution-gas base cost beyond memory expansion for its return-data region, matching RETURN. Its once-per-transaction nonce, payer, and maximum-cost effects are covered by the transaction intrinsic cost (PR #12003, merged Jul 23). If incrementing the nonce creates tx.sender, the approving frame must also cover 120 * 1,530 = 183,600 state gas.

Execution Flow ​

For each frame transaction:

  1. Check tx.nonce == state[tx.sender].nonce
  2. Initialize sender_approved = false, payer = None
  3. For each frame, compute resolved_target: if frame.target is null, use tx.sender; otherwise use frame.target
  4. Charge the resolved target's EIP-2929 warm/cold account access from the frame's execution budget at frame entry, before the value balance check and dispatch (PR #12211, merged Aug 20). If the budget cannot cover it, the frame halts exceptionally. An active precompile target is then called as an ordinary call would call it (PR #12157); a codeless target runs default code
  5. Execute each frame sequentially with independent limits.execution and limits.state pools and CALLVALUE = frame.value at the top-level call (which is 0 except in SENDER frames):
    • DEFAULT mode: caller = ENTRY_POINT, execute as regular call to resolved_target
    • VERIFY mode: caller = ENTRY_POINT, execute as STATICCALL to resolved_target; approval-bearing validation frames must call APPROVE
    • SENDER mode: requires sender_approved == true, caller = tx.sender, target = resolved_target. If caller lacks balance for frame.value, the frame reverts (ordinary CALL value-transfer semantics).
  6. After all frames: verify payer != None, apply the transaction-level storage refund and calldata floor to the execution dimension, add net state gas, charge the payer for final gas_used plus any blob base fee, and return payer_refund

Validation prefix and execution body (PR #12471, merged Oct 9): the validation prefix is the frames up to and including the first frame after whose execution payer is set; the remaining frames are the execution body. A frame that sets payer and then reverts does not end the prefix, the prefix never ends inside an atomic batch, and a transaction in which no frame sets payer is invalid. The boundary changes no processing; it exists so the mempool rules and sibling EIPs such as EIP-7906 can refer to it.

Execution approval is transaction-wide. Once sender_approved is set, every later SENDER frame is authorized, not only the frame the validator inspected. Custom validation must therefore commit to the complete later frame list or constrain every later SENDER frame before calling APPROVE (PR #11939, merged Jul 17).

EOA Default Code ​

When frame.target has no code, the protocol applies built-in "default code" behavior:

VERIFY mode:

  1. Resolve the frame target (null means tx.sender). Execution approval is only valid for the sender.
  2. Read the approval scope from the flags: allowed_scope = frame.flags & 3. If allowed_scope == 0, revert.
  3. Select the signature index by scope: index 0 when the scope includes execution, otherwise index 1 for payment-only approval.
  4. Require that entry to be a SECP256K1 signature with empty msg whose resolved signer equals the resolved frame target.
  5. Rely on the protocol-validated secp256k1 signature over compute_sig_hash(tx).
  6. Call APPROVE(allowed_scope).

Default code has no execution gas of its own; its only execution charge is the frame-entry access charge (100 gas for the pre-warmed sender, 2,600 for a cold sponsor on first touch). A default-code VERIFY frame whose execution budget cannot cover that charge invalidates the transaction (PR #12211).

PR #11481 (merged May 22) moved per-tx signatures out of frame.data and into a dedicated outer signatures list. PR #11814 (merged Jul 7) replaced the earlier scan with index 0; PR #11954 (merged Jul 17) restored codeless EOA sponsorship by reserving index 1 for payment-only default VERIFY. A codeless sender can therefore authenticate at index 0 while a distinct codeless EOA sponsor authenticates at index 1 with the sponsor address in sig.signer (an empty signer resolves to tx.sender). PR #11621 (merged May 11) removed the P256 branch from the protocol-shipped default code. P256 remains a protocol-validated outer signature scheme, but codeless EOAs still get only secp256k1 default-code authentication; accounts that need passkeys or other schemes use deployed code plus SIGPARAM/SIGDATACOPY custom verification.

SENDER and DEFAULT modes: PR #11621 (merged May 11) changed default code so that SENDER and DEFAULT frames no longer revert. The previous behavior (revert unconditionally on both modes, plus an RLP-call-batch decoder removed by PR #11577 on Apr 29) blocked simple native ETH transfers to a fresh EOA via a frame transaction. After the merge, a SENDER or DEFAULT frame whose resolved_target has no code completes the value transfer and returns with empty data.

This means any EOA can use frame transactions today, no smart contract deployment needed.

Atomic Batching ​

Consecutive frames with bit 2 of flags set form an atomic batch. The batch is the maximal contiguous run of flagged frames terminated by a frame without the flag:

Frame 0: (atomic flag set)   ─┐
Frame 1: (flag not set)      ─┘ Batch 1
Frame 2: (atomic flag set)   ─┐
Frame 3: (atomic flag set)   ─│ Batch 2
Frame 4: (flag not set)      ─┘

Only DEFAULT and SENDER frames may participate. PR #11652 (merged May 12) originally opened batching to every mode; PRs #11955 and #11987 (merged Jul 21) moved the VERIFY exclusion into consensus-validity rules. PR #12109 (merged Aug 14) then statically prohibited approval-scope flags on every batch member, including the terminating frame, so a batch cannot call APPROVE or roll back payer, nonce, or execution-approval context. If any frame in a batch reverts, state and logs are restored to before the batch started, state-gas receipt mutations are reversed, and remaining frames in the batch are skipped. Skipped frames record receipt status 0x2; PR #11953 (merged Jul 17) corrected the earlier draft value 0x3.

Gas Accounting ​

PR #12062 (merged Aug 13) replaced each frame's single gas limit with explicit [execution, state] budgets. Execution gas meters computation, data, and access; state gas meters durable state growth under EIP-8037. The pools cannot borrow from each other or from another frame. GAS reports only execution gas; TXPARAM(0x0c) reports current-frame state gas left, while FRAMEPARAM(0x09-0x0b) exposes declared state gas and completed-frame execution/state usage.

python
frame_tx_intrinsic_gas = (
    12_000
    + 475 * len(tx.frames)
    + frame_data_cost
    + signature_data_cost
    + signature_verification_cost
    + value_transfer_cost
)

standard_gas_limit = (
    frame_tx_intrinsic_gas
    + sum(frame.limits.execution for frame in tx.frames)
    + sum(frame.limits.state for frame in tx.frames)
)

max_gas = max(
    standard_gas_limit,
    calldata_floor_gas + sum(frame.limits.state for frame in tx.frames),
)

The intrinsic cost fell from 15,000 to 12,000. A non-zero value transfer to a non-sender target adds the 6,000-gas EIP-2780 value cost. The intrinsic cost plus all declared execution budgets, and the calldata floor independently, must fit EIP-7825's TX_MAX_GAS_LIMIT = 16,777,216; state budgets are bounded by block state-gas capacity instead. ARBITRARY, secp256k1, and P256 entries still add 100, 2,800, and 6,700 execution gas.

The calldata floor now follows EIP-7976: every frame-data and signature byte counts uniformly at 64 gas, while the standard intrinsic keeps zero/non-zero weighting (PR #12209, merged Aug 21; EIP-7623 replaced by EIP-7976 in requires by PR #12395, merged Sep 29).

State-gas charges are attributed to the frame that created the state. If a later frame clears a slot created earlier in the transaction, the refill reduces the owning earlier frame's receipt and refunds the payer without becoming spendable by the later frame. Reverts journal both state and these receipt mutations.

Storage refunds follow EIP-3529 at transaction scope. The EIP-7976 calldata floor applies to the execution component, and net state gas is then added:

python
gas_used_before_refund = standard_gas_limit - tx_unused_gas
applied_refund = min(refund_counter, gas_used_before_refund // 5)
gas_used_after_refund = gas_used_before_refund - applied_refund

tx_state_gas = sum(receipt.gas_used.state for receipt in frame_receipts)
tx_execution_gas = max(gas_used_after_refund - tx_state_gas, calldata_floor_gas)
gas_used = tx_execution_gas + tx_state_gas

The payer buys exactly the execution and state capacity the transaction consumes:

python
blob_gas = len(blob_versioned_hashes) * GAS_PER_BLOB
max_cost = max_gas * max_fee_per_gas + blob_gas * blob_base_fee
charged_fee = gas_used * effective_gas_price + blob_gas * blob_base_fee
payer_refund = max_cost - charged_fee

max_cost must fit in one EVM word. Payment approval collects it from the payer before execution; settlement returns payer_refund. Blocks reserve execution and state capacity separately. Per-frame receipts exclude intrinsic execution gas and transaction-level refund/floor adjustments, so their sum generally differs from transaction-level gas_used.

Block accounting follows EIP-7778 (PR #12226, merged Aug 24): the block's execution dimension counts gas before the storage refund, block_execution_gas = max(gas_used_before_refund - tx_state_gas, calldata_floor_gas), while the payer still pays the post-refund gas_used. If EIP-3298 activates alongside, its PR #12455 removes the refund cap from frame settlement as well.

Blob Support ​

Frame transactions may carry blobs. Each hash must be a KZG versioned hash; blob-carrying transactions follow EIP-4844 inclusion, blob-gas, and BLOBHASH rules, while using the EIP-7594 pooled-transaction sidecar wrapper. A blobless frame transaction must set max_fee_per_blob_gas = 0.

The payer covers blob_gas * blob_base_fee. max_fee_per_blob_gas is only an inclusion cap, not an escrow price, and blob fees are not refunded based on frame outcomes. Because blobs are optional, the same transaction type supports ordinary calls and gas-sponsored data posting (PR #11985, merged Jul 23).

Receipt and Network Encoding ​

The consensus receipt payload is [cumulative_gas_used, payer, [frame_receipt, ...]], with each frame receipt encoded as [status, [execution_gas_used, state_gas_used], logs]. The fork's Receipts message mirrors this nested data. A later state-gas refill may reduce an earlier frame's final state usage. PR #12008 (merged Jul 28) defines transaction logs as the concatenation of frame-receipt logs in frame order; logs from an unrolled atomic batch are empty. PR #12061 (merged Aug 14) clarifies that the receipt carries no transaction-level status, so interfaces derive one from the frame statuses.

Blob-carrying frame transactions use the EIP-7594 sidecar wrapper in PooledTransactions; block-body responses contain the plain transaction payload. Blobless frame transactions use the plain payload everywhere.

Canonical Signature Hash ​

python
def compute_sig_hash(tx):
    for sig in tx.signatures:
        if len(sig.msg) == 0:
            sig.signature = Bytes()  # elide raw signature bytes
    return keccak(bytes([FRAME_TX_TYPE]) + rlp(tx))

The transaction-type prefix aligns EIP-8141 with the EIP-2718 typed-transaction convention and prevents cross-type signature replay (PR #11544, merged Apr 22). Frame metadata and frame data, including a SENDER frame's value and an expiry-verifier deadline, remain covered by this hash.

Raw signature bytes are elided for signatures whose msg is empty because:

  1. A signature over compute_sig_hash(tx) cannot commit to its own raw bytes.
  2. Custom verifiers need to insert witness bytes after computing the canonical hash.
  3. Protocol-validated signatures can remain aggregation-compatible, because contracts see metadata but not raw bytes.

This is the Jul 6-7 repair from PR #11837 and PR #11814. The older model elided VERIFY frame data; the current model keeps frame data in the hash and moves self-referential witness bytes to the signatures list.

Expiry Verifier Frame ​

A VERIFY frame whose frame.target equals EXPIRY_VERIFIER (0x81413f0cF12e9b6a49B1D0439E081c577D57FfFf) is an expiry verifier frame. It calls the canonical runtime code at that address; the calldata is interpreted as an 8-byte big-endian unix-seconds deadline, and the call reverts unless block.timestamp <= expiry_timestamp.

PR #12387 (merged Oct 6) changed how the verifier exists: instead of being installed at fork activation at address(0x8141), it is an ordinary contract deployed by a keyless (Nick's-method) pre-EIP-155 transaction, so the address is identical on every chain and the fork changes no state. The PR body says it "is not special in any way beyond the public mempool recognizing it." EIP-8250's NONCE_MANAGER and EIP-8272's recent-root contract adopted the same deployment pattern on Oct 8.

Constraints:

  • frame.flags == 0
  • frame.value == 0
  • frame.limits.state == 0
  • len(frame.data) == EXPIRY_DATA_LENGTH (8)
  • At most one expiry-verifier frame per transaction
  • The frame succeeds without calling APPROVE; public-mempool validation shapes (self_verify, only_verify, and pay) are the approval-bearing frames. PR #11662 relaxed the previously-uniform "every VERIFY frame must call APPROVE" rule to "if the frame reverts, the transaction is invalid".

Mempool admission: if present, an expiry-verifier frame may only be the first frame in the frame list for public propagation. Nodes MUST drop a transaction from the public mempool whose expiry is less than the node's current view of block.timestamp at any point. The TIMESTAMP opcode is permitted only in an expiry-verifier frame executing the canonical runtime code. Clients may omit explicit EVM execution and perform the deadline check natively when the externally observable result is identical, but its validation work still counts against MAX_VERIFY_GAS.

Validation-prefix shape matching treats expiry-verifier frames as transparent: [expiry_verify, self_verify] is recognized as [self_verify] for admission-rule purposes.

Mempool Policy ​

The policy below is the restrictive tier of a two-tier mempool architecture. It is what clients ship first and what FOCIL nodes default to. An expansive tier (ERC-7562 / paymaster-extended) is intended to develop in parallel for use cases that exceed the restrictive policy (privacy protocols, multi-account paymasters).

The public mempool recognizes four validation prefixes:

Self Relay:

[self_verify]                    # basic
[deploy] → [self_verify]        # with account deployment

Canonical Paymaster:

[only_verify] → [pay]                    # basic
[deploy] → [only_verify] → [pay]        # with account deployment

The validation prefix is the consensus term defined under Execution Flow (PR #12471). Rules enforced during the validation prefix:

  • Must match one of the four prefixes above
  • Sum of validation-prefix execution budgets plus intrinsic signature-validation cost <= MAX_VERIFY_GAS (100,000), and sum of validation-prefix state budgets <= MAX_VERIFY_STATE_GAS (500,000)
  • self_verify, only_verify, and pay frame flags must match the scope of the APPROVE call; no frame in the validation prefix may set the atomic-batch flag
  • No VERIFY frame may appear after the validation prefix
  • Banned environmental opcodes include TIMESTAMP, BLOCKHASH, fee fields, and SLOTNUM. PR #12066 (merged Aug 11) banned SLOTNUM because it changes between simulation and inclusion. ORIGIN, TLOAD, TSTORE, and BLOBHASH are permitted because their results are frame- or transaction-determined (PR #12167, merged Aug 18). CREATE, CREATE2, and SETDELEGATE remain limited to the first deploy frame. The spec still names EIP-7819's SETDELEGATE even though that EIP was Declined for Inclusion in Hegotá on Sep 14
  • No state writes, except inside the first deploy frame for CREATE/CREATE2/SETDELEGATE operations that install code at tx.sender, or SSTOREs to tx.sender's storage
  • No storage reads outside tx.sender
  • No calls to non-existent contracts or EIP-7702 delegations (except deploy-frame default-code behavior at tx.sender)
  • Deploy-frame target may be any contract, provided its execution satisfies the trace rules above. EIP-7997 is the canonical-but-non-mandatory factory; cross-chain-stable factory addresses are typically acquired through it (PR #11567)

When every validation-prefix frame has protocol-defined semantics (default code, the canonical expiry verifier, or the canonical paymaster), nodes may evaluate those semantics directly instead of executing EVM code. Direct evaluation must enforce the same execution/state-gas and paymaster rules and track the sender, payer, expiry-code/deadline, and timestamp dependencies for revalidation (PR #12001, merged Jul 23).

Canonical paymaster: verified by runtime code match, uses reserved balance accounting. The canonical paymaster handles ETH-funded sponsorship only (the paymaster covers gas from its own ETH balance, with no token-level repayment flow). ERC-20 gas repayment is a separate non-canonical paymaster design space: a public-mempool sponsor can inspect signature metadata and the next SENDER frame while accepting sponsee frontrunning risk; a fully trustless onchain balance-checking variant exceeds the restrictive tier and routes privately or through an expansive tier. See Mempool Strategy → ERC-20 gas repayment.

python
available = balance(paymaster) - reserved_pending_cost - pending_withdrawal_amount

Non-canonical paymaster: limited to 1 pending tx per paymaster in the mempool.

Replacement and exposure: PR #12007 (merged Jul 28) identifies pending transactions by (sender, nonce). A replacement must independently pass admission and raise both execution-fee fields by the node's configured increment, conventionally 10%; blob replacements also follow blob-pool fee rules. Payer reservations move atomically if the payer changes. Every payer, including a codeless EOA sponsor, has aggregate maximum-cost exposure bounded by its balance. Nodes evict invalid transactions first, then the nearest expiry, then the lowest effective priority fee.

Producer re-execution bound: a transaction pays nothing until a frame approves payment, so a block producer SHOULD bound unpaid re-execution of a validation prefix that never approves, and MAY evict it after a bounded number of consecutive failed build attempts (PR #12213, merged Sep 29). This is local policy; the bound should tolerate transient failures such as a payer funded earlier in the same block.

Transaction origination: EIP-3607's restriction (which forbids transactions whose tx.sender has non-empty, non-delegation code) does not apply to frame transactions. SENDER frames intentionally originate calls where tx.sender is a contract account, so the carve-out is required for native AA. Validation logic for non-frame transaction types is unchanged: a regular transaction is only valid if the sender account's code is empty or a valid delegation indicator (PR #11272, merged May 5).

Practical Use Cases ​

1. Simple EOA Transaction (gas self-paid) ​

FrameModeTargetData
0VERIFYsenderEmpty; uses outer signature index 0
1SENDERtargetcall data

Frame 0 verifies the signature and calls APPROVE(0x3). Frame 1 executes.

2. Gas Sponsorship (ETH-funded, canonical paymaster) ​

FrameModeTargetData
0VERIFYsenderSignature (approve execution)
1VERIFYcanonical paymasterSponsor data (approve payment)
2SENDERtargetUser's call
3DEFAULTcanonical paymasterPost-op (settle gas refund)

The canonical paymaster pays gas in ETH; the user pays nothing.

3. Atomic Approve + Swap ​

FrameModeAtomicTargetData
0VERIFY-senderSignature
1SENDERsetERC-20approve(DEX, amount)
2SENDERnot setDEXswap(...)

If the swap reverts, the ERC-20 approval is also reverted.

4. Account Deployment + First Transaction ​

FrameModeTargetData
0DEFAULTdeployerinitcode + salt
1VERIFYsenderSignature
2SENDERtargetUser's call

Frame 0 deploys the account; frames 1-2 validate and execute.

5. EOA Paying Gas in ERC-20s ​

FrameModeTargetData
0VERIFYsenderEmpty; uses sender signature entry at index 0
1VERIFYsponsorSponsor data; checks signature metadata and next ERC-20 transfer
2SENDERERC-20transfer(sponsor, fees)
3SENDERtargetUser's call
4DEFAULTsponsorOptional post-op refund/conversion

The sponsor pays ETH gas; frame 2 repays the sponsor in ERC-20 tokens.

Mempool note: in the current public-mempool shape, the sponsor does not check the user's ERC-20 balance onchain during validation. It checks the frame structure and any sponsor authorization data, then accepts the risk that the sponsee may zero the ERC-20 balance before inclusion. A fully trustless onchain balance-checking paymaster remains consensus-valid, but it exceeds the restrictive tier because it reads external token storage.

Key Design Properties ​

  • No authorization list: Unlike EIP-7702, doesn't rely on ECDSA for delegation. Compatible with PQ crypto.
  • No access list: Future optimizations covered by block-level access lists (EIP-7928).
  • Per-frame value field: SENDER frames may transfer ETH natively via frame.value (added by PR #11534, Apr 16). VERIFY and DEFAULT frames must set value = 0, preserving STATICCALL-like behavior in VERIFY and keeping ENTRY_POINT free from funding transfers.
  • ORIGIN returns frame caller: Changed from traditional tx.origin behavior (precedent set by EIP-7702).
  • Transient storage cleared between frames: TSTORE/TLOAD state doesn't persist across frames.
  • Warm/cold state shared across frames: Gas accounting for storage access is shared. PR #12113 pins the initial warm addresses to tx.sender, coinbase, and active precompiles, and storage keys start cold. Each frame pays its resolved target's access at entry (PR #12211), which is also how the payer becomes warm.
  • Requires: EIP-1559, EIP-2718, EIP-2780, EIP-3529, EIP-3607, EIP-4844, EIP-7594, EIP-7702, EIP-7708, EIP-7778, EIP-7825, EIP-7976, and EIP-8037. The August two-dimensional-gas merge added the state-gas, value-pricing, transfer-log, and execution-cap dependencies; EIP-7778 (pre-refund block gas) arrived Aug 24, and EIP-7976 replaced EIP-7623 on Sep 29. EIP-7997 remains optional.
ProposalRelationship
ERC-43378141 is the native protocol successor, removing the bundler intermediary
EIP-7702Complementary; 7702 accounts can also use frame transactions. Note: 7702-delegated accounts cannot currently use default code signature verification (gap identified by DanielVF)
ERC-75628141's mempool rules are inspired by but simpler than 7562 (no staking/reputation)
EIP-8175Competing alternative: flat capabilities + programmable fee_auth, 4 new opcodes
EIP-8130 + EIP-8430Coinbase/Base's alternative, split on Oct 8 into sibling standards: EIP-8430 (pending) is a fixed-cost secp256k1 transaction type (0x79) with call phases, sponsorship, and 2D nonces, and EIP-8130 "Keystore Accounts" is an actor and authenticator registry that plugs into it. The Keystore also names EIP-8141 frame accounts as a consumer. Base lists EIP-8430 for its Everest upgrade. See EIP-8130 + EIP-8430
EIP-7997Canonical deterministic factory predeploy; recommended for cross-chain-stable factory addresses but no longer a hard dependency after PR #11567 (merged Apr 30)
EIP-7392Signature registry; interoperability PR #11455 was closed without merge on Apr 23
EIP-8250Keyed-nonces sibling EIP, CFI for Hegotá since Sep 24. Keyed-nonce first use costs 97,920 state gas (#12279), each key 12,100 access gas with a block-access-list entry (#12457), and nonce_seq == 2**64 - 1 marks single-use keys (#12511). NONCE_MANAGER is now a Nick's-method deployment at 0x8250968C... (#12440). Open PR #12039 proposes keyed-nonce mempool concurrency
EIP-8266Expiring-nonces sibling EIP (PR #11692 merged May 22, co-authored by nerolation and lightclient); second EIP in the compose-by-requires AA stack, with requires including both EIP-8141 and EIP-8250. Sentinel-mode (tx.nonce == 2**64 - 1) plus a NONCE_RING system contract; complements PR #11662's per-tx EXPIRY_VERIFIER frame by scoping nonces themselves to time windows
EIP-8272Recent-roots sibling EIP, CFI for Hegotá since Sep 24. PR #12281 (merged Sep 4) removed its envelope field and RECENTROOTREFLOAD opcode in favor of a canonical recent_root_verify VERIFY frame, which ended the 0xb5 collision with SIGDATACOPY; the frame counts toward MAX_VERIFY_GAS (#12302) and its contract is a Nick's-method deployment at 0x8272D967... (#12443)
EIP-8288In-mempool signature and proof aggregation (PR #11772, merged Sep 9; renamed Sep 12). Adds DEP_VERIFY = 4 frames and a block-level recursive_stark proof; recursive-STARK soundness is an explicit trust assumption, and only leanSPHINCS dependencies are usable until LEANSTARK_SCHEME is defined. Proof placement remains open
EIP-8397Frame Authenticator Signatures (leekt, PR #12244, merged Oct 14): adds the AUTHENTICATOR (0x3) signature scheme with a fixed 50,000-gas state-independent check and SIGPARAM(0x04) for key_id
EIP-7906Transaction Assertions (CFI Sep 24; co-authored by lightclient and AnkushinDaniil since October): an ASSERT = 3 frame mode plus TXTRACE (0xb6) and EVENTDATACOPY (0xb7) let a wallet attach onchain outcome checks; a failed assertion rolls the execution body back to the end of the validation prefix
EIP-8369VOPS Profiles for FOCIL Eligibility (PR #12110, merged Sep 1, PFI Sep 2): end-of-payload and bounded-replay profiles for inclusion-list eligibility
EIP-8209Commit-Reveal Transaction Frames (forshtat, shahafn): COMMIT = 5 and REVEAL = 6 modes for front-running protection; not proposed for Hegotá
ERC-8286First application-layer standard built on EIP-8141, merged as ERC PR #1794 on Jul 28. It defines how ERC-7579 modular accounts apply a validator module's returned approval mode through APPROVE during a VERIFY frame; ERC PR #2008 (Sep 13) adds declared protocol or contract execution routes
ERC-7902Wallet capabilities rewritten for EIP-8141 (ERC PR #2091, merged Oct 20): EIP-5792 capabilities for paymaster frames, keyed nonces, expiry, recent roots, atomic frame batches, and ASSERT frames
ERC-8403 / ERC-8421 (pending)Account Authority Lifecycle (AnkushinDaniil) standardizes key add/rotate/revoke with a normative EIP-8141 binding; Frame Transaction Alternative Mempools (Yoav Weiss and the ERC-4337 team) defines a stake-and-reputation alternative mempool for frame transactions

Key Takeaway ​

A frame transaction is a sequence of purpose-labeled sub-calls. The protocol runs validation frames first, refuses to proceed unless approval-bearing validation frames call APPROVE, then runs execution frames. Default code makes EOAs first-class users without deployment. The mempool only propagates transactions whose validation prefix fits a constrained shape, which is what lets a stateless node safely accept them.

  • EOA Support — what existing codeless accounts get for free, and how default code replaces EIP-7702 delegation for common cases.
  • Feedback Evolution — how the spec got to its current shape through twenty-nine phases of community review.
  • Mempool Strategy — why the validation prefix is the way it is, and how the two-tier mempool handles everything that doesn't fit.
  • Competing Standards — how EIP-8141 compares to EIP-8130, EIP-8175, EIP-8202, and the sibling proposals.