EIP.tools

EIP.tools

⚠️ DraftStandards Track: ERC

ERC-8421: Frame Transaction Alternative Mempools

Alternative mempools framework for EIP-8141 Frame Transactions that extend the public mempool with stake and reputation.

Authors
Created2026-09-21
Discussion Linkhttps://ethereum-magicians.org/t/erc-8421-frame-transaction-alternative-mempools/29800
Requires

Markdown

https://raw.githubusercontent.com/forshtat/ERCs/re...

EIP-GPT summary

Contents
AbstractMotivationSpecificationConstantsMempool TypesAlternative MempoolsRule TypesDefinitionsExecution ModelThe preverify frame subclassStaking Registry ContractAssociated Storage Rules (ASSOC)Validation Prefix and Structure (PREFIX)Budgets (BUDGET)Signatures (SIGNATURE)Opcode Rules (OPCODES)Contract Creation (CREATION)Calls and Code Access (CALLING)Storage and State Access (STORAGE)Local Rules (LOCAL)Stake (STAKING)Payer Solvency (SOLVENCY)Reputation (REPUTATION)DefinitionsCalculationGeneral rulesUnstaked entitiesBlame attributionReplacement, Eviction and Revalidation (LIFECYCLE)Propagation (PROPAGATION)Acceptance AlgorithmRationaleRelationship to the public mempoolRationale for per-entity verification gas budgetsNo cap on state gasKeyed nonces and per-sender limitsState modifying preverify framesMitigating the mass invalidation attackBackwards CompatibilitySecurity ConsiderationsCopyright

Abstract

EIP-8141 defines a new EIP-2718 transaction type and a set of rules such transactions need to follow in the canonical public mempool. These canonical mempool rules are chosen to be relatively simple and universal in a way that enables a number of high priority use cases. Other rulesets can exist to serve use cases made impossible by the canonical mempool rules, however without a public mempool such transactions would require a private submission mechanisms. This document defines a framework for alternative mempools with customized validation rulesets for EIP-8141 Frame Transactions. The rulesets define which transactions a node may admit to the mempool, which it rejects, and how it tracks the entities that form a transaction's validation process.

This document also defines the standard alternative mempool, a default ruleset for a permissionless and decentralized public Frame Transactions mempool that is less restrictive than the canonical one.

Motivation

A frame transaction replaces a hard-coded signature check with EVM code that runs during a validation prefix. Before a mempool node relays such a transaction, it must execute the entire validation prefix code. If the prefix depends on mutable state that anyone can change, a single state change can invalidate many pending transactions at once, and a node that spends resources on those transactions is never paid. This is the mass invalidation attack. Mempools must put in place carefully designed sets of rules to bound this threat.

ERC-4337 relies on rules defined in ERC-7562 to solve the same problem for UserOperations. Frame Transactions differ from UserOperations in ways that make defining a shared rule set inconvenient. This document defines the Frame Transaction specific mempool rules in a way that maintains a full backward compatibility with use cases that existed in ERC-4337, like autonomous ERC-20 Token Paymasters, privacy pool withdrawals and more.

Specification

Constants

NameValueDescription
MAX_VERIFY_GAS_PER_ENTITY100_000Maximum execution gas budget for a single unstaked or default-code entity's validation frames.
MAX_VERIFY_GAS_STAKED_ENTITY1_000_000Maximum execution gas budget for a single staked entity's validation frames.
MIN_UNSTAKE_DELAY86400One day. A withdrawal delay long enough to deter most Sybil attacks.
MIN_STAKE_VALUEper-chainA non-trivial but not excessive amount, roughly the equivalent of USD 1000 in the native token.
SAME_NONCE_KEY_MEMPOOL_COUNT4Maximum pending transactions that select the same (sender, nonce key) pair (EIP-8250).
SAME_SENDER_MEMPOOL_COUNT64Maximum pending transactions from one unstaked sender, regardless of how many nonce keys they select.
SAME_UNSTAKED_ENTITY_MEMPOOL_COUNT10Base number of pending transactions that may reference the same unstaked sponsoring payer.
THROTTLED_ENTITY_MEMPOOL_COUNT4Pending transactions allowed for a throttled entity.
THROTTLED_ENTITY_LIVE_BLOCKS10Blocks a transaction referencing a throttled entity may stay in the mempool.
THROTTLED_ENTITY_BLOCK_COUNT4Transactions referencing a throttled entity that a node may include in one block it builds.
MIN_INCLUSION_RATE_DENOMINATOR10Denominator in the reputation formula.
THROTTLING_SLACK10Lets an entity legitimately fail some transactions without being throttled.
BAN_SLACK50Lets a throttled entity fail some transactions without being banned.
MAX_TXS_ALLOWED_UNSTAKED_ENTITY10000Upper bound on included when computing the allowance of an unstaked sponsoring payer.
STAKING_REGISTRY_ADDRESSper-chainAddress of the Staking Registry contract (see Staking Registry Contract).

Mempool Types

This document relates to three distinct types of mempool rulesets for Frame Transaction mempools:

  1. The canonical public mempool, as defined by EIP-8141 in the Mempool section.
  2. The standard alternative mempool, as defined by this document.
  3. The non-standard alternative mempools, which are defined by third party mempool operators as defined in Alternative Mempools section.

A transaction that violates a canonical public mempool rule MUST NOT be propagated over the public mempool, as EIP-8141 requires. It may only be propagated over the appropriate alternative mempool's own transport if it satisfies its rules. One transaction may be propagated over multiple alternative mempools if it satisfies all of their rules.

Alternative Mempools

The standard alternative mempool defined by this document is not the only possible rule set. Node operators may agree on alternative mempools, rule sets that a node opts into in addition to the standard mempool. Each alternative mempool is identified by its own topic, conventionally the IPFS hash of a document that describes its rules. A transaction that violates a standard rule MUST NOT be propagated in the standard mempool, but may be propagated in any alternative mempool whose rules it satisfies. Reputation counters (seen and included) should be kept separately for each mempool, so that an entity that is throttled in one mempool is unaffected in another.

Rule Types

Public transaction mempools are distributed among multiple nodes in a peer-to-peer network, while each node maintains its own view of the mempool and participant reputations at all times. Additionally, certain nodes may choose to act as solo submission channels with custom rules but without a connection to a peer-to-peer network. Therefore, there are two types of validation rules: network-wide rules and local node rules.

A violation of any rule by a frame transaction results in the transaction being rejected from submission or dropped from the mempool if necessary, and therefore prevented from being included in future blocks.

A peer-to-peer mempool networks rely on participant reputations to limit the threat of mass transaction invalidation. A network-wide rule is a rule whose violation by a transaction damages the reputation of the peer that sent that transaction into the standard mempool. A peer with critically low standing is treated as a spammer according to the Propagation Rules.

A local rule depends on a node's own mempool contents and its local tracking of entities' reputations. Different nodes may hold different mempool contents, so no consensus is possible and peers are never penalised for a local rule violation. Local rules are collected in the Local Rules section, and all other rules are network-wide.

Definitions

  1. Validation prefix: the shortest prefix of a transaction's frames whose successful execution sets payer, as defined by EIP-8141. All Frames that appear after the validation prefix regardless of their type belong to the execution body of the Frame Transaction and are largely outside this document's scope.
  2. Validation frame: a frame in the validation prefix regardless of its mode, type or scope.
  3. Frame Subclasses: a heuristic classification of a Validation Frame within a Frame Transaction based on its role and behaviour in the transaction validation process. The EIP-8141 mode subclassifications defines the following subclasses: self_verify, only_verify, pay, expiry_verify and deploy; the pre_verify subclass is additionally defined in this document.
  4. Entity: a smart contract that a Validation Frame executes directly. Entities are defined by their role in a transaction, similarly to Frame Subclasses:
    • The sender is tx.sender. It runs the self_verify or only_verify frame.
    • The payer is the resolved target of the frame that calls APPROVE with a payment scope. It runs the pay frame, or the self_verify frame if sender and payer is the same entity.
    • The factory is the resolved target of the deploy frame. Every validation frame is attributed to exactly one entity. An expiry_verify frame is attributed to no entity as its code is protocol-defined.
  5. Default-code entity: an entity whose account has the empty code hash and therefore executes EIP-8141's default code. It has no bytecode to trace, is never staked, and is exempt from the opcode, call and storage rules.
  6. Staked entity: an entity that has a stake of at least MIN_STAKE_VALUE and an unstake delay of at least MIN_UNSTAKE_DELAY, as reported by the Staking Registry smart contract, and whose stake is not being withdrawn.
  7. Associated storage: a storage slot of any contract is associated with a given address according to the Associated Storage Rules.
  8. Canonical paymaster: a contract whose runtime code exactly matches the canonical paymaster implementation defined by EIP-8141.
  9. Admission validation: the simulation a node performs before it first accepts a transaction.
  10. Revalidation: a re-simulation of a pending transaction against a newer head or a candidate block, as described in Replacement, Eviction and Revalidation.
  11. Spammer: a peer that attempts to exhaust the mempool network by sending a large number of transactions that were never valid.
  12. Mass invalidation attack: a series of actions by which a large number of transactions, having passed admission validation and propagated through the mempool network, later become invalid and ineligible for inclusion.

Execution Model

VERIFY frames run in static mode. The non-static DEFAULT mode frames in the validation prefix are allowed for two subclasses:

  • The deploy frame as defined in EIP-8141
  • The pre_verify frame

Rules in this document that mention writes, contract creation or value calls consequently take effect only in those frames.

The pre_verify frame subclass

A pre_verify frame is a DEFAULT-mode frame whose resolved target is the same as the resolved target of the approving VERIFY frame (self_verify, only_verify, pay) that immediately follows it. Each approving frame MAY be preceded by at most one pre_verify frame. A pre_verify frame is distinguishable from the deploy frame as it does not create code in the tx.sender address.

The code of an approving VERIFY frame that is preceded by a pre_verify frame MUST check the status of that pre_verify frame before it calls APPROVE, using the frame status parameter of FRAMEPARAM, and MUST NOT call APPROVE if that status is not success.

According to EIP-8141, a failed DEFAULT mode frame does not invalidate the transaction even if it is reverted in the validation prefix, so without this check the approving frame would approve after the state writes it depends on had been reverted. Although mempool nodes reject at admission a transaction whose pre_verify frame does not succeed in simulation, smart contracts cannot rely on mempool rules for their security.

Staking Registry Contract

Stake is kept in a specialized designated contract at STAKING_REGISTRY_ADDRESS.

It implements the following interface:

interface IStakingRegistry {
    /// Lock `msg.value` as the caller's stake, with the given unstake delay.
    function addStake(uint32 unstakeDelaySec) external payable;

    /// Begin the withdrawal delay. From this point the caller is not considered to be staked.
    function unlockStake() external;

    /// Withdraw the stake after the delay has passed.
    function withdrawStake(address payable withdrawAddress) external;

    /// Return the stake information.
    function getDepositInfo(address account)
        external
        view
        returns (uint256 stake, uint32 unstakeDelaySec, uint64 withdrawTime);
}

Associated Storage Rules (ASSOC)

Several rules below grant an entity broader access to storage that is associated with it, rather than only to a contract's own account storage. Associated storage identifies the slots a well-behaved contract is expected to use to track state for a specific address, such as an ERC-20 balance mapping keyed by that address, without requiring the contract to declare in advance which slots those are.

  • [ASSOC-010] A storage slot of any contract is associated with address A if the slot's own value equals A.
  • [ASSOC-020] A storage slot of any contract is associated with address A if the slot was computed as keccak256(A || x) + n, where x is a bytes32 value and n is an integer in the range 0 to 128. This covers the common Solidity mapping and dynamic array layouts keyed or indexed by A, together with a fixed run of slots reachable from them.

A node determines storage association by testing the slots a validation frame has actually accessed using specialized simulation and tracing interfaces.

Validation Prefix and Structure (PREFIX)

  • [PREFIX-010] The validation prefix MUST match one of the following shapes. A transaction whose prefix does not match any of them MUST be rejected.

    • [self_verify]
    • [deploy, self_verify]
    • [only_verify, pay]
    • [deploy, only_verify, pay]

    In every shape, each approving frame (self_verify, only_verify or pay) MAY be immediately preceded by one pre_verify frame, as [PREFIX-110] describes. An optional single expiry_verify frame is always allowed as the first frame of the validation prefix.

  • [PREFIX-020] If a deploy frame is present it MUST be the first frame of the prefix, not counting a leading expiry_verify frame. There is at most one deploy frame. The deploy frame MUST result in a successful deployment of the tx.sender contract.

  • [PREFIX-040] No frame in the validation prefix may carry ATOMIC_BATCH_FLAG.

  • [PREFIX-050] No VERIFY frame may follow the validation prefix.

  • [PREFIX-060] A transaction MUST be rejected if any validation frame reverts, or a VERIFY frame exits without its required APPROVE.

  • [PREFIX-080] A node MUST reject or drop a transaction whose expiry_verify deadline is earlier than the node's view of the current block timestamp.

  • [PREFIX-100] The following types of frames are exempt from alt-mempool rules: frame whose target is a default code account, a canonical paymaster, or the EXPIRY_VERIFIER contract. A node MAY evaluate them directly instead of simulating them. It MUST still apply the same limits it would apply normally.

  • [PREFIX-110] The target of a pre_verify frame MUST have deployed code.

  • [PREFIX-120] The DEFAULT mode frame in the validation prefix that is neither the deploy frame nor a pre_verify frame MUST cause the transaction to be rejected.

Budgets (BUDGET)

  • [BUDGET-010] A node MUST track the sum of limits.execution separately per entity, over that entity's own validation frames. The pre_verify frame counts toward the entity of the approving frame it immediately precedes. The intrinsic cost of validating tx.signatures counts toward the tx.sender. For unstaked entities, that sum MUST NOT exceed MAX_VERIFY_GAS_PER_ENTITY. For staked entities, that sum MUST NOT exceed MAX_VERIFY_GAS_STAKED_ENTITY.

Signatures (SIGNATURE)

  • [SIGNATURE-010] Before simulating any frame, a node MUST validate every protocol-validated signature (SECP256K1, P256 (EIP-7951)) against its own signed message: the transaction's signature hash when msg is empty, or the explicit digest msg carries otherwise. A transaction with any invalid signature MUST be rejected.

Opcode Rules (OPCODES)

Every validation frame is bound by the banned opcodes of EIP-8141's Validation Trace Rules, except for the frames [PREFIX-100] exempts. This section lists only the differences.

  • [OPCODES-010] BALANCE (0x31) and SELFBALANCE (0x47) are allowed for a staked entity. They remain banned for every other entity.
  • [OPCODES-020] SSTORE is not banned outright. The Storage and State Access rules decide which frames may write and where.
  • [OPCODES-030] Any unassigned opcode is blocked.
  • [OPCODES-040] A revert on "out of gas" is forbidden, because it can leak the gas limit or the call-stack depth.

Contract Creation (CREATION)

  • [CREATION-010] CREATE, CREATE2 and SETDELEGATE (EIP-7819) are allowed only inside the deploy frame, and only to install code at tx.sender. Any one of these opcodes may be executed at most once, and it MUST install code for tx.sender.

Calls and Code Access (CALLING)

  • [CALLING-010] Using an address that has no deployed or default code is forbidden.
  • [CALLING-040] Precompiles that access nothing in the blockchain state or environment are allowed. These include the core precompiles 0x01 to 0x11 and the P256VERIFY precompile.

Storage and State Access (STORAGE)

Storage access by SLOAD, SSTORE, TLOAD and TSTORE is restricted as follows. Note that storage writes are possible only in deploy and pre_verify frames. Transient storage (EIP-1153) accessed with TLOAD and TSTORE is treated exactly like persistent storage accessed with SLOAD and SSTORE.

  • [STORAGE-000] Access to storage is always restricted unless allowed by one of the following rules.
  • [STORAGE-010] Access to tx.sender's own storage is always allowed.
  • Access to storage associated with tx.sender in an external contract that is not an entity of the transaction is allowed if either:
    • [STORAGE-021] the sender's account already exists, meaning the transaction has no deploy frame; or
    • [STORAGE-022] the transaction has a deploy frame and the factory is a staked entity.
  • If an entity is staked it is additionally allowed:
    • [STORAGE-031] access to its own storage;
    • [STORAGE-032] read-only access to any storage in a contract that is not an entity of the transaction.
    • [STORAGE-033] write access to slots associated with the entity address in any contract that is not an entity of the transaction;

Local Rules (LOCAL)

These rules depend on the other transactions in a node's own mempool and have no network propagation effects. A node applies them when it admits a transaction. A transaction that violates one is rejected without any reputation change for the peer that sent it.

  • [LOCAL-010] A transaction MUST NOT use as its factory or its sponsoring payer an address that is tx.sender of another pending transaction in the mempool. A factory or paymaster contract can therefore not also serve as an account.
  • [LOCAL-020] A transaction MUST NOT use storage associated with its sender, or with a staked entity, in a contract that is tx.sender of another pending transaction in the mempool.

Stake (STAKING)

Note that there are no penalization mechanisms in the alternative mempools protocol and the stake is never slashed. It exists only as a configurable mechanism for sybil attack prevention. The significant lock-up period introduces capital cost of creating new abusive entities.

  • [STAKING-010] An entity is staked if the Staking Registry reports for it a stake of at least MIN_STAKE_VALUE and an unstake delay of at least MIN_UNSTAKE_DELAY, and withdrawal has not been initiated.

Payer Solvency (SOLVENCY)

  • [SOLVENCY-010] For every payer, including the sender when it pays for itself, a node MUST track reserved_pending_cost(payer), the sum of the maximum costs of every pending transaction in its mempool that names this payer. A node MUST reject a transaction if available_balance(payer) is less than its maximum cost, where available_balance(payer) = balance(payer) - reserved_pending_cost(payer).
  • [SOLVENCY-020] For a canonical paymaster, available_balance additionally subtracts pending_withdrawal_amount(paymaster), the amount of any delayed withdrawal currently pending in that paymaster.
  • [SOLVENCY-030] On admission a node increases reserved_pending_cost by the transaction's maximum cost. It decreases it on eviction, replacement, inclusion and removal by reorg. When a replacement changes the payer, the node moves the reservation to the new payer atomically with the replacement.

Reputation (REPUTATION)

Definitions

  1. seen: a per-entity counter of how many times this node received a unique valid transaction that references the entity. It counts transactions received over RPC and over the mempool network. Admitting a replacement for an existing pending transaction is not a new occurrence for this purpose; [REPUTATION-040] governs it instead.
  2. included: a per-entity counter of how many transactions that were previously counted in seen for that entity were included in a canonical block. A node determines this from the block's transactions and receipts.
  3. Refresh rate: every hour, both counters are updated as value = value * 23 // 24. The effect is a practical reputation reset after four days of entity inactivity.
  4. inclusionRate: the ratio of included to seen.

An ACTIVE staked entity faces no additional limit under the reputation rules. There is no cap on its pending transactions, or on its transactions in a block a node builds. An entity whose transactions are frequently not included loses its reputation, until declines below a certain threshold and gets additional limitations.

Calculation

Let max_seen = seen // MIN_INCLUSION_RATE_DENOMINATOR. The following conditions partition every entity into exactly one reputation state:

  • BANNED: max_seen > included + BAN_SLACK
  • THROTTLED: included + THROTTLING_SLACK < max_seen <= included + BAN_SLACK
  • ACTIVE: max_seen <= included + THROTTLING_SLACK

A new entity starts as ACTIVE. Reputation is tracked per entity address, not per role. The refresh rate limits an entity's organic climb toward BANNED, allowing a relatively small number of invalid transactions per hour without any penalties.

Let opsAllowed = SAME_UNSTAKED_ENTITY_MEMPOOL_COUNT + inclusionRate * min(included, MAX_TXS_ALLOWED_UNSTAKED_ENTITY), the pending-transaction allowance for an unstaked sponsoring payer ([REPUTATION-220]). For a new entity, with included = 0, this is SAME_UNSTAKED_ENTITY_MEMPOOL_COUNT.

General rules

The following rules apply to all staked entities and to unstaked sponsoring payers.

  • [REPUTATION-010] A BANNED address is not allowed into the mempool. Every pending transaction that references it is removed.
  • [REPUTATION-020] A THROTTLED address is limited to THROTTLED_ENTITY_MEMPOOL_COUNT entries in the mempool, to THROTTLED_ENTITY_BLOCK_COUNT transactions in a block the node builds, and to THROTTLED_ENTITY_LIVE_BLOCKS blocks of residency in the mempool.
  • [REPUTATION-040] Admitting a replacement is not a new occurrence of seen for any unchanged entity. If the replacement changes the payer, the factory, or both, the node decrements each changed role's old address's seen by 1 and increments its new address's seen by 1, atomically with the replacement.

Unstaked entities

  • [REPUTATION-210] A THROTTLED sender is limited to THROTTLED_ENTITY_MEMPOOL_COUNT pending transactions in total, regardless of how many nonce keys it uses.
  • [REPUTATION-220] An unstaked sponsoring payer that is neither THROTTLED nor BANNED may have at most opsAllowed pending transactions in the mempool.

Blame attribution

The alternative mempool system tracks which entity was the one responsible for a transaction that has been previously admitted to the mempool to become invalid. This is done by detecting the exact VERIFY frame in the validation prefix that changes its behaviour and no longer executes the expected APPROVE opcode call.

  • [REPUTATION-310] If a transaction fails revalidation because of the factory or the sender entities, the sponsoring payer's seen is decremented by 1. A payer must not lose reputation because of another entity's failure.
  • [REPUTATION-320] If a staked factory is used and the sender's validation frame fails, the factory's seen is not decremented under [REPUTATION-310]: it absorbs the failure in its own inclusionRate, exactly as if its own frame had failed.
  • [REPUTATION-330] If a staked sender is used, its reputation is affected by failures of all other entities of the transaction, even if those entities are staked.

Replacement, Eviction and Revalidation (LIFECYCLE)

  • [LIFECYCLE-010] A pending transaction is identified by (sender, nonce_keys, nonce_seq), as defined by EIP-8250. A node MAY admit a transaction only if its nonce_seq is the next contiguous sequence value for each key in its nonce_keys: either the key's on-chain sequence, current_nonce_seq(sender, key), or one more than the nonce_seq of a pending transaction of the same sender that selects that key. Forming a nonce gap on any key is not allowed.

  • [LIFECYCLE-020] Two transactions of the same sender conflict if they have the same nonce_seq and their nonce_keys share at least one key, as at most one of them can ever be included. The mempool MUST NOT hold two conflicting transactions. A transaction that conflicts with one or more pending transactions is a replacement for all of them. A replacement MUST be valid under every rule in this document. A node SHOULD accept and propagate it only if it increases both max_fee_per_gas and max_priority_fee_per_gas by at least 10% over each transaction it replaces. A replacement MAY name a different factory or payer contract. On accepting a replacement, a node removes every transaction it replaces, and evicts every pending transaction of the sender that no longer satisfies [LIFECYCLE-010].

  • [LIFECYCLE-030] A node MUST keep at most SAME_NONCE_KEY_MEMPOOL_COUNT pending transactions that select any one (sender, key) pair. A transaction with several nonce_keys counts once against each of its keys. A node MUST keep at most SAME_SENDER_MEMPOOL_COUNT pending transactions of an unstaked sender, regardless of how many nonce keys they select. A staked sender has no sender-wide limit while ACTIVE; [REPUTATION-020] limits it once it is THROTTLED.

    These limits count only the keys selected by pending transactions. Because the mempool never holds conflicting transactions, a replacement releases every key that a replaced transaction selected and the replacement does not. For example, replacing a pending transaction with nonce_keys = [1, 3, 5] by one with nonce_keys = [1, 5] at the same nonce_seq releases key 3: a new transaction may select key 3 at its on-chain sequence, and a pending transaction that selected key 3 at the next sequence is evicted under [LIFECYCLE-020].

  • [LIFECYCLE-040] When a new block is accepted, a node MUST remove the transactions the block includes and update payer reservations. It MUST revalidate every pending transaction that depends on state the block changed.

    This includes at least:

    • transactions for the same sender
    • transactions whose recorded storage dependencies changed
    • transactions whose payer's balance or code changed
    • transactions that reference an entity whose stake status changed

    A transaction that no longer satisfies the rules MUST be evicted. To optimize the revalidation flow, a node should record, for each admitted transaction, the set of state it depended on: the storage slots read, the code, balance and nonce of every address whose value the validation used. It should use this set to select the transactions that require revalidation, without the need to re-validate the others.

Propagation (PROPAGATION)

The wire protocol is out of scope for this document. The following rules apply to any transport that carries transactions between nodes of the standard mempool.

  • [PROPAGATION-010] A transaction is broadcast with two items: the transaction itself, and the block hash against which it was last validated.
  • [PROPAGATION-020] A node that receives a transaction from a peer MUST validate it locally before it propagates it.
  • [PROPAGATION-030] If a received transaction fails a static check, such as an invalid encoding, a value below a minimum, or an outdated block hash, the node drops it and keeps the connection.
  • [PROPAGATION-040] A node silently drops a transaction that conflicts ([LIFECYCLE-020]) with a transaction recently included in a block. This is almost certainly a network race. It causes no reputation change.
  • [PROPAGATION-050] If a received transaction fails against the current block, the node should retry validation against the block named in the transaction's message. If it succeeds, the node silently drops the transaction and keeps the connection. If it fails this is an indicator of a peer propagating a known invalid or incompatible transaction payload. The node should mark the sending peer as a spammer, disconnect from it, or block it permanently.

Acceptance Algorithm

A node applies the rules in this order:

  1. Validate the signatures.
  2. Determine the validation prefix and check its structure.
  3. Resolve each entity's role, address and stake ([STAKING-010]) and check reputation.
  4. Simulate the prefix and trace it, applying [OPCODES], [CREATION], [CALLING] and [STORAGE] rules to every validation frame.
  5. Check payer solvency and reserve the cost.
  6. Check the local rules, the per-sender limitations
  7. If the transaction is a replacement, apply the replacement rules.
  8. If every check passes, record the dependency set, admit the transaction and propagate it.

Rationale

Relationship to the public mempool

EIP-8141's public mempool is deliberately narrow, which is the correct choice for a protocol consensus affecting rules in a decentralized network. However, such a narrow ruleset cannot host a wide range of useful applications of the core Frame Transaction architecture: a shielded pools with Merkle roots as paymasters, registries of authorised signers, or an ERC-20 token paymaster with budgeting code and its own storage. Stake and reputation give a node what the public mempool lacks by design: an economic cost for creating an abusive entity, and a mechanism that throttles an entity once it causes invalidations.

Because the standard mempool extends the public mempool rather than replacing it, the two stay consistent. A wallet author who targets the public mempool needs no knowledge of this document.

Rationale for per-entity verification gas budgets

A single combined gas budget for the whole validation prefix, as EIP-8141 uses, cannot be raised for a staked entity without also raising it for every unstaked entity in the same transaction, since the rule only sees one sum. The alternative mempool tracks the sum separately per entity instead, so a staked payer, sender or factory can be given MAX_VERIFY_GAS_STAKED_ENTITY, a materially higher allowance for more expensive validation logic such as signature aggregation or a Merkle proof check, while every unstaked entity of the transaction remains bound by MAX_VERIFY_GAS_PER_ENTITY, exactly as it would be in a transaction with no staked entity at all.

No cap on state gas

EIP-8141 caps limits.state (EIP-8037) at MAX_VERIFY_STATE_GAS across the validation prefix. This document places no cap on state gas. A payer's solvency check already reserves the cost of every frame's declared limits.state, so a large budget is paid for, and the prefix structure already limits where state can be written. A deploy frame that needs a large state gas budget for a code deposit can declare it without hitting a mempool-specific limit.

Keyed nonces and per-sender limits

EIP-8250 keyed nonces let one shared sender serve many independent users, typically a privacy protocol in which every user selects a fresh nonce key at sequence 0. Every such transaction selects its own key, so SAME_NONCE_KEY_MEMPOOL_COUNT never binds, and only the sender-wide limit bounds the sender. That limit applies to unstaked senders only. A staked sender is already accountable for every failure of its transactions ([REPUTATION-330]), so a mass invalidation of its pending transactions throttles it, and [REPUTATION-020] then bounds it as it bounds any other staked entity.

Treating any two transactions that cannot both be included as a replacement keeps the pending transactions of a sender free of conflicts, so a node can track each key's pending sequences independently, and a limit on a key counts only the transactions that actually select it.

State modifying pre_verify frames

ERC-4337 validation functions may write storage, under the same associated-storage and stake rules that govern reads. One common use is a paymaster that pulls ERC-20 tokens from the sender during validation, so that it is reimbursed before it commits to pay. VERIFY frames are static, so the same guarantee needs a non-static frame that runs first.

The pre_verify subclass marks such a frame, binds it to one approving frame so that each write is attributed to an entity, and allows only one per approving frame. Attribution lets the storage and reputation rules apply to writes exactly as they apply to reads.

Mitigating the mass invalidation attack

The mass invalidation attack can be carried out in any of the three ways listed in its definition. To prevent them, validation code runs in a sandbox. It is isolated from other transactions, from external storage changes, and from environment information such as the block timestamp.

A transaction that fails admission validation and never enters the mempool is not an attack. Nodes are expected to apply ordinary measures against spam, such as throttling by API key, IP address, or peer score. An attack is also not considered economically viable if invalidating N transactions costs the attacker N * X for a sufficiently large X.

Backwards Compatibility

The rules in this document preserve the ERC-4337 use cases that ERC-7562 made possible, even though neither the EntryPoint contract nor a UserOperation structures or handleOps bundles exist. Each of those use cases depended on a specific relaxation of the mempool's validation rules, and this document keeps the equivalency of restrictions and relaxations with ERC-7562.

A contract written against ERC-7562's rules therefore needs no change in its core validation architecture to adopt Frame Transactions. The differences are concentrated in the exposed interfaces, where for example validateUserOp and validatePaymasterUserOp calls are replaced by self_verify/only_verify and pay frames respectively, and initCode execution is replaced by the deploy frame.

This document introduces no consensus change and requires no change to EIP-8141 or the FOCIL rules of EIP-7805 and similar. It does not modify ERC-4337 or ERC-7562.

Security Considerations

Staking Registry. The stake provisions depend on a registry contract outside the EIP-8141 protocol. Correctness of the deployed Staking Registry contract is critical for the security of the entire alternative mempool system.

Staked entities can misbehave temporarily. A staked entity can cause a bounded amount of invalidation before its reputation drops. The bound is BAN_SLACK * MIN_INCLUSION_RATE_DENOMINATOR / 24 invalid transactions per hour, plus whatever throttling then allows. It is a rate limit, not a guarantee.

pre_verify frames run before approval. A pre_verify frame is called by ENTRY_POINT, before any APPROVE has happened, so nobody has been authorised yet. The target of a pre_verify frame SHOULD check that the transaction's sender, as reported by TXPARAM, is the party whose state it is about to change.

A failed DEFAULT frame in the validation prefix does not invalidate the transaction automatically. Only VERIFY failures do, so a pre_verify frame that reverts on-chain lets the transaction continue. The approving frame MUST check the pre_verify frame's status. A node cannot check the requirement, so a payer that ignores it bears the loss.

Approval covers all following SENDER frames. sender_approved is a single transaction-scoped flag. Once it is set, every SENDER frame in the transaction executes as tx.sender, not only the frame the approving code inspected. Wallet code that approves execution SHOULD bind its approval to the whole frame list, for example by verifying a signature over the canonical signature hash, which commits to every frame. A signature over an explicit digest that does not commit to the frame list authorises an open-ended set of SENDER frames.

ARBITRARY signatures. The protocol does not validate them, so a transaction that carries one is only as trustworthy as the frame that inspects it.

Canonical paymaster. A canonical paymaster is exempt from the trace rules and admitted by code match. This puts a lot of responsibility on the canonicalized code's correctness.

Default-code payers. A payer with no code is bounded only by the solvency rules. A sponsor that moves its balance elsewhere between admission and inclusion invalidates every pending transaction it sponsors, up to the balance it appeared to hold. Reservation limits the exposure to the payer's balance at admission time and does not remove it.

Revalidation load. A new head can force many revalidations. The lifecycle rules allow a node to select only the affected transactions. A node that ignores the filtering of affected transactions would expose itself to a load attack proportional to the size of its mempool.

Copyright and related rights waived via CC0.

EIP.tools

EIP.tools

Search, read, and map Ethereum improvement proposals, ERCs, RIPs, and CAIPs from one focused interface.

Farcaster
by @apoorveth