EIP-8141 Frame Transactions (Native Account Abstraction) implemented in revm, demonstrated with a permissionless shielded withdrawal.
Shielding is the path toward private transfers on Ethereum. But to withdraw anonymously, you need a fresh account with no on-chain history. That account has no ETH to pay gas.
You either fund it from a known account (linking you to the withdrawal) or trust a centralized relayer (introducing censorship risk). Both break the privacy guarantee.
Ethereum transactions hardcode the sender as the gas payer. There's no native way to separate "who authorized this" from "who pays for it."
A Frame Transaction (type 0x06) replaces the single-signature model with an ordered list of frames. Each frame runs independently with its own gas budget, caller identity, and purpose.
VERIFY frame data is elided from the signature hash. The authentication proof isn't part of what gets signed. You can prove who you are without anyone else in the transaction seeing how.
New tx type (0x06) with RLP encoding and sig hash computation. APPROVE opcode with scoped authorization. TXPARAM* opcodes for transaction introspection. Frame execution handler with per-frame gas isolation, checkpoint-based state, transient storage clearing. JSON-RPC devnet node with frame-aware receipts.
Wallets in raw EVM bytecode with ECDSA ecrecover auth (Solidity can't emit the custom APPROVE opcode). Unified JoinSplit circuit (2-in, 2-out) in Noir with Poseidon commitments -- one circuit handles deposits, withdrawals, and transfers. UltraHonk verifier (~11KB) verified on-chain via BN254 pairing precompiles.
Alice deposits 1 ETH into a shielded pool with a JoinSplit proof (0 inputs, 1 output). A fresh account -- zero ETH, no history -- withdraws that 1 ETH with another JoinSplit proof (1 input, 0 outputs). A sponsor pays gas via a VERIFY frame. Both proofs use the same unified circuit and verifier.
The sponsor approves payment for anyone. A real system needs rules: token balance, membership, reputation.
EIP-8141's primary goal. Dilithium/SPHINCS+ in a VERIFY frame is possible but would need a precompile or very expensive EVM verification.
The main open research question. Replacing ECDSA with a ZK proof in VERIFY is feasible (the frame just calls APPROVE), but not implemented. Which proof systems fit the gas budget? How do verifiers interact with APPROVE? What does the calldata format look like when the proof is elided from the sig hash?
VERIFY data is visible in the mempool before block inclusion. ZK proofs in VERIFY would close this (proof reveals nothing). FOCIL ensures the tx can't be censored while waiting.
Gas sponsorship native to the tx format. A fresh account withdraws from a pool without ever touching ETH. No funding link, no relayer.
Today's pools need relayer networks for gas. With frames, gas abstraction is at the transaction level. Pools focus on cryptography, not gas plumbing.
A sponsor that only pays for group members. ZK proof of membership in VERIFY -- without revealing which member. Works with SNARKs or STARKs.
VERIFY frames can check arbitrary predicates via ZK: group membership, credentials, reputation -- without revealing who you are. Gated sponsorship, conditional access, privacy-preserving compliance.
Multi-sig, social recovery, time-locked approvals. All VERIFY frame logic. No protocol changes needed.
ZK at the frame level hides who you are. A privacy-preserving contract hides what you're doing. FOCIL prevents censorship. Stack all three: nobody knows who sent a transaction, nobody can infer what it does, nobody can stop it.
One wallet holds ETH for gas, sponsors all your other accounts. One VERIFY authenticates, another approves payment. Not private by default, but a ZK proof in the payment frame hides the link.
Which proof systems fit the gas budget? How do verifier contracts interact with APPROVE? This is the foundation for everything else -- mempool privacy, membership sponsoring, private intents.
Today's pools assume relayer networks for gas. That assumption goes away. New designs should focus on commitment schemes and Merkle structures.
Keep the revm fork compatible with upstream. Serve as a reference implementation for client teams.
Rust 1.85+. JoinSplit proofs take ~3s to generate.