EIP-8141: Frame Transaction

@derek By the way, what is the motivation for atomic batching only being defined for SENDER frames? Doesn’t it prevent DEFAULT frames from relying on transaction level post-transaction assertion modules?

Good point – I think we wanted to exclude VERIFY frames from atomic batching because that’d make validating transactions more difficult since you need to make sure VERIFY frames are not reverted by other frames, but I don’t see a reason why DEFAULT frames should be excluded too. In fact, I think it might even be OK to allow any frames (including VERIFY) to be atomically batched, and simply forbid atomic batching with VERIFY frames in the mempool rules (but not in the protocol itself). That way, if private pools want to use atomically batched VERIFY frames to enable use cases like revert protection, they are free to do so. What do you think?

3 Likes

Read through the thread carefully. Adding a contract-level perspective that maps onto a few of the still-open debates.

Background: we’ve been operating EVVM, a smart-contract-native virtual blockchain framework, since 2023. It runs validation, signature schemes, async nonces, batched execution, and gas sponsorship inside Core.sol. ~200 community deployments across 10+ EVM-compatible chains. Each instance can configure its own rules independently of the others on the same host.

Three observations from the production context that overlap with current discussion:

1. The “what about institutional rules” gap. Most of the thread reasons about a universal frame transaction. Some real users (banks, regulated DeFi, public-sector pilots) need per-environment policy: KYC/AML gates, allowlists, custom delegatecall guards in front of execution. EVVM instances configure those policies through per-deployment contracts. None of that is reachable at protocol level without breaking universality, and 8141 correctly does not try to. Worth being explicit in the spec or rationale that the contract layer remains the place where policy variance lives, because real adopters will land there first.

2. Async-execution compatibility as a contract-level property. @DanielVF and @chunter’s concerns about Monad / Base / Tempo are real for protocol-level validation. EVVM-style validation sidesteps that entire class because it runs inside the contract at execution time, against the post-state of prior transactions in the block. The host chain treats it as a regular contract call. Async execution and contract-level AA can coexist by design: nothing in this model depends on validation being known at mempool time. Not an argument against 8141, an architecture point that may be worth referencing for chains where 8141 cannot ship.

3. Two implementation choices in 8141 that we made differently, observable in EVVM today:

  • Per-operation success tracking in batches, vs the all-or-nothing atomic batching in @derek’s recent PR. EVVM’s batchPay returns bool[] results. The trade-off between application-class needs (e.g. independent dust transfers vs approve-then-swap dependencies) is one we hit early; whether 8141’s atomic-only mode covers both classes cleanly or forces the per-op case into separate transactions is worth checking before lock-in.

  • Non-authoritative reservation as the only reservation primitive (covered in the EIP-8250 thread). We deliberately did not ship authoritative locks because of DoS-by-lock-grabbing and bad-UI lockup vectors; this likely matters at protocol level too if keyed nonces ship.

References:

Best,
German Abal / @ariutokintumi
Co-Founder, Architect & Security of EVVM

1 Like

Some super tiny nits as I’m reading the spec:

  • frame.target is None → should this be frame.target = b""?
  • APPROVE_PAYMENT_AND_EXECUTION → should be APPROVE_EXECUTION_AND_PAYMENT to match the order of evaluation.
  • Point 3 of the policy summary is confusing.
  • “paymaster frame” isn’t really defined before it’s used.

Random other thoughts:

  • This proposal is consuming five opcode slots. Is that acceptable? The alternatives aren’t particularly attractive.
  • Why make FRAMEDATACOPY revert on out of bounds when CALLDATACOPY does not? Is there a benefit that outweighs the extra FRAMEPARAM(0x04, ...) call for contracts that know exactly how much they need to copy?
1 Like

Sounds good. By the way, do you think the same can be said about other things where VERIFY frames are treated differently, say, for example the SSTORE not being allowed on the protocol level vs. as a mempool rule?

Afaik, VERIFY frames are implictly batched to anything… a reverted VERIFY renders the entire TX invalid

My understanding is that the reason why VERIFY frames must not do SSTORE is because we want frame transactions to maintain the invariant that even if you remove all the VERIFY frames from a txn, the txn will still do the same thing. That way, block builders can aggregate VERIFY frames and remove them from txns, which is what allows VERIFY frames to carry large quantum signatures (since they will be removed anyways).

That’s true, but currently no other frames may revert a VERIFY frame, whereas if we allowed a VERIFY frame to be batched with other frames, it could be reverted by another frame.

@alex-forshtat-tbk atomic batching now supports any frames: Update EIP-8141: Support atomic batching with any frames by derekchiang · Pull Request #11652 · ethereum/EIPs · GitHub

1 Like

Awesome, thank you! :folded_hands:

Sounds really cool, and I would like to learn more about the details of how this aggregation can be done in practice.
To be clear, I am not pushing for non-static VERIFY frames, it intuitively makes sense that verification is a static call - I just wanted to make sure there is a clear rationale for other opcodes being limited in the mempool rules, but not SSTORE etc.
Also, if state changes make it harder to aggregate a VERIFY frame, should we think about rephrasing the behaviour of APPROVE (i.e. “Increment the sender’s nonce… and collect the transaction’s maximum cost from payer”)?