Workspace IndexKnowledge Notes › ERC-8141

#33PoC

ERC-8141

Native account-abstraction explainer — Ethereum's protocol-level Frame Transactions.

Read-only explainer — no wallet needed.

Why

A protocol-native preview of what this project's application-layer AA demos (session keys, atomic batching) do today with smart contracts and delegation — EIP-8141 proposes moving those same properties into Ethereum's base transaction format itself.

How it works

Not a working demo by necessity: EIP-8141 defines a new transaction type where a single transaction carries a sequence of frames (a VERIFY frame for signature/fee authorization, then one or more EXECUTE frames) instead of one implicit call — but no client or RPC can send this transaction type yet, since it requires execution-layer support the network doesn't have. As of writing it's only "considered for inclusion" in a future fork, so this stays a diagram/explainer page rather than a live demo.

The ACDE readout, and the two kinds of "no" (2026-08-28)

The call was set to conclude between this proposal and EIP-8130, and as of writing no public readout confirms an outcome. What the developer timeline did in that gap is the useful part: the argument moved off the content and onto the weight. The recurring sentence was "the direction is right, but this is too heavy for the current stage" — and that is a schedule objection, not a technical one.

The distinction is worth holding onto because the two look identical from outside and demand opposite responses:

The objection What it actually says What you do next
"This is wrong" the design does not achieve the goal change the design
"This is not now" the design is right and too large to land here split the scope

Hearing the second and redesigning is wasted work; hearing the first and merely deferring is worse. The question to ask in the room is which one you are being given — and the tell is usually whether the objection survives when you make the proposal smaller.

Review clarification

The basic concept, from zero

Ethereum has two kinds of accounts, and only the dumb one can act. An EOA can start transactions, but its rules are frozen into the protocol: one ECDSA key, one sequential nonce, fees paid by the sender in ETH, one call per transaction — lose the key, lose the account. A contract account is fully programmable but cannot initiate anything. Account abstraction is the project of erasing that split: let the account that acts also be programmable — in who may sign, how fees are paid, and what one transaction may contain.

Today's AA is an emulation built one layer up: ERC-4337 rebuilt a transaction system out of contracts (UserOperations, bundlers, an EntryPoint), and EIP-7702 lets an EOA borrow contract code. It works, at the price of extra actors, extra gas, and extra trust surfaces. EIP-8141 proposes ending the emulation: a new base transaction type made of frames — one VERIFY frame ("here is the proof this is authorized, and how fees get paid") followed by one or more EXECUTE frames (the calls, atomically: all or nothing). The two jobs every transaction always had — prove it's allowed, then do things — become explicit, separate, programmable parts of the format itself.

The same action, three generations of code

Today, the node's checks are hard-coded and unchangeable:

assert(ecrecover(tx.sig) == tx.from);     // exactly one ECDSA key
assert(tx.nonce == account.nonce);        // exactly one nonce
assert(balance[tx.from] >= gas * price);  // sender pays, ETH only
call(tx.to, tx.data);                     // exactly one call

ERC-4337 replays those checks inside a contract — EntryPoint.handleOps loops over UserOperations calling account.validateUserOp and then account.execute, with a bundler carrying the batch and a paymaster optionally paying. Every hop is the emulation tax.

Under EIP-8141 the node itself runs the loop the EntryPoint used to fake:

tx = { type: FRAME_TX, frames: [
  { kind: VERIFY,  target: myAccount,
    input: { scheme: "p256-passkey", proof, feeToken: USDC } },
  { kind: EXECUTE, target: USDC, data: approve(dex, 100e6) },
  { kind: EXECUTE, target: dex,  data: swap(USDC, ETH, 100e6) },
]}

and the account's own verify code is where the features live — a session key, natively:

function verify(Proof p, Frame[] fs) external view returns (bool) {
    if (p.signer == owner) return checkSig(p);
    Session s = sessions[p.signer];              // a temporary key
    require(block.timestamp < s.expiry);         // ...that expires
    require(allCallsTo(fs, s.allowedContract));  // ...only this app
    require(totalValue(fs) <= s.perTxLimit);     // ...small amounts
    return checkSig(p);
}

Who it makes happy

Who Today's pain With frame transactions
Users Seed phrase or bust; approve-then-swap leaves a dangling approval; need ETH first Passkey as the native key; approve+swap atomic; fees in tokens or sponsored
Wallet builders Run or rent bundler + paymaster infrastructure Those services largely disappear; the chain validates directly
dApp/game/agent builders Session keys need a smart-wallet stack per provider Bounded delegation is a base-layer feature
The protocol A parallel 4337 mempool; EntryPoint as a shared choke point One canonical mempool, no single trusted contract

Concrete situations it improves: the dangling-approve accident (two EXECUTE frames make approval-without-swap impossible); onboarding without ETH (a sponsor pays inside VERIFY); lost-key recovery as account logic instead of a custodian's feature; the post-quantum migration (signature schemes become account code to upgrade, not protocol constants to fork); and agent commerce (an AI agent holding a session key with expiry, an allowed contract, and a per-transaction limit is delegation with a chosen blast radius).

The honest cost — and most of why ACDE said "too heavy": the VERIFY frame is arbitrary code deciding mempool validity before anyone has paid, so it must be strictly gas-bounded and cheaply re-checkable, or invalid transactions become a free DoS vector.

"Then ERC-4337 could be sunsetted?" (jay, 2026-09-03)

Right direction, wrong tense. 4337 was always the stopgap — enshrinement was the stated endgame, and 8141's VERIFY/EXECUTE split is essentially validateUserOp/execute promoted into the transaction format. So 4337 doesn't get killed; it gets absorbed — the concepts survive as the contracts empty out. But the sunset is a decade-scale decay, for four reasons: nothing on Ethereum is ever removed (the EntryPoint is immortal, and millions of deployed and counterfactual smart-account addresses don't migrate themselves); the native-AA competition is unsettled (8141 vs 8130 vs Tempo — a workaround with users beats a proposal without a fork date); L2s break the symmetry (4337 works identically on every EVM chain today, while native AA lands chain by chain — cross-chain wallets may be its last stronghold); and the bundler/paymaster vendors will pivot to the new rails rather than defend the old ones, accelerating the very sunset that obsoletes them. As strategy — don't build a moat out of 4337 plumbing — the sentence is already true. As a forecast — traffic to zero — add ten years and an asterisk.

Progress (2026-09-08)

Vitalik's 9/6 Frames update reported movement: on the 8/27 call the proposal went CFI → SFI (considered → scheduled for inclusion), slotted for Hegotá (targeted 2027 Q2) alongside FOCIL. SFI is an assignment, not a completion — the tell to watch after the 9/10 devnet-priority list is whether a devnet actually attaches to 8141. Two framing notes. The headline 'pay gas in stablecoins' is a consequence, not the design: the design separates the three jobs that today share one signer — authorization, gas payment, execution — and stablecoin fees are what fall out once gas payment is its own strand inside VERIFY. And the competition is asymmetric on timing: rival EIP-8130 targets a Base deployment in September, so the L2 implementation becomes real before the L1 standard does — a workaround with users, again, outrunning a proposal with a fork date.

The same runtime-vs-spec point the invariant card makes applies to the objection here: liquid-issuance-not-authorization is why an enshrined VERIFY frame must be strictly gas-bounded and cheaply re-checkable — arbitrary validity code that runs before anyone pays is a premise the network cannot afford to trust unconditionally.

Related code

# ERC-8141 — a transaction carries a sequence of frames instead of one implicit call:
# a VERIFY frame (signature/fee authorization) followed by one or more EXECUTE frames.
# Simulates the frame structure and runs it in sequence, aborting if VERIFY fails.

from dataclasses import dataclass, field
from typing import Callable


@dataclass
class Frame:
    kind: str  # "VERIFY" or "EXECUTE"
    description: str
    run: Callable[[dict], bool]


@dataclass
class FrameTransaction:
    frames: list[Frame] = field(default_factory=list)

    def execute(self, context: dict) -> bool:
        for frame in self.frames:
            print(f"  [{frame.kind}] {frame.description} ...", end=" ")
            ok = frame.run(context)
            print("OK" if ok else "FAILED")
            if frame.kind == "VERIFY" and not ok:
                print("  -> VERIFY frame failed: transaction aborted before any EXECUTE frame runs.")
                return False
            if frame.kind == "EXECUTE" and not ok:
                print("  -> EXECUTE frame failed: transaction reverts.")
                return False
        return True


def verify_signature_and_fee(ctx: dict) -> bool:
    return ctx.get("signature_valid", False) and ctx.get("balance", 0) >= ctx.get("max_fee", 0)


def execute_transfer(ctx: dict) -> bool:
    ctx["balance"] -= ctx["transfer_amount"]
    return ctx["balance"] >= 0


def execute_approve(ctx: dict) -> bool:
    ctx["allowance"] = ctx.get("allowance", 0) + ctx["approve_amount"]
    return True


def build_transaction() -> FrameTransaction:
    return FrameTransaction(frames=[
        Frame("VERIFY", "signature + fee authorization", verify_signature_and_fee),
        Frame("EXECUTE", "transfer 50 tokens", execute_transfer),
        Frame("EXECUTE", "approve spender for 20 tokens", execute_approve),
    ])


if __name__ == "__main__":
    print("EIP-8141 Frame Transaction — VERIFY then EXECUTE, EXECUTE, ...\n")

    print("Case 1: valid signature, sufficient balance")
    ctx = {"signature_valid": True, "balance": 100, "max_fee": 5, "transfer_amount": 50, "approve_amount": 20}
    ok = build_transaction().execute(ctx)
    print(f"Transaction succeeded: {ok}, final state: {ctx}\n")

    print("Case 2: invalid signature — VERIFY frame blocks all EXECUTE frames")
    ctx = {"signature_valid": False, "balance": 100, "max_fee": 5, "transfer_amount": 50, "approve_amount": 20}
    ok = build_transaction().execute(ctx)
    print(f"Transaction succeeded: {ok}")

Where it lands in Jayverse

  • Rabbit: track 8141's progress, don't redesign around it yet. With the proposal at SFI targeting Hegotá (~2027 Q2), keep rabbit's ERC-4337/EIP-7702 session-key and mandate stack as the near-term plan — treat native frame transactions as a decade-scale migration to watch, not a reason to pause current AA work.
  • Rabbit: prototype a session key as a VERIFY frame when a testnet exists. Once any client exposes frame transactions on a public testnet, build a minimal session-key mandate (expiry, allowed contract, per-tx limit) as VERIFY-frame logic — it maps directly onto rabbit's existing mandate model and is the cheapest way to validate the migration path early.
  • Devnet: gas-bound any custom validateUserOp-style check the same way. Since an enshrined VERIFY frame must be strictly gas-bounded and cheaply re-checkable to avoid a free DoS vector, apply that same bound-and-recheck discipline to rabbit's own account-validation code running on devnet today.

Key expressions

Words and phrases from this page worth keeping, with the Korean meaning and the sentence they come from.

Expression뜻 · 쓰이는 자리
considered for inclusion포함이 검토 중인 단계 · 제안이 아직 채택 전, 논의 대상일 뿐임을 표현. "it's only "considered for inclusion" in a future fork"
readout(회의 후) 결과 요약 보고 · 콜이 끝난 뒤 공개되는 결론 요약을 가리킴. "no public readout confirms an outcome"
sunset (동사)단계적으로 폐지하다, 퇴장시키다 · 오래된 시스템을 서서히 없앤다는 뜻. "Then ERC-4337 could be sunsetted?"
stopgap임시방편, 땜질용 조치 · 영구적 해법이 나올 때까지 쓰는 수단. "4337 was always the stopgap"
at the price of~을 대가로 치르고 · 이득을 얻는 동시에 지불하는 비용을 말할 때. "at the price of extra actors, extra gas"
dangling approval붕 뜬(미완료) 승인 상태 · approve만 되고 후속 실행은 안 된 상태. "leaves a dangling approval"
seed phrase or bust시드 문구 아니면 끝장 · "~or bust"는 양자택일을 강조하는 구어체. "Seed phrase or bust"
outrun~을 앞지르다, 추월하다 · 경쟁 구도에서 한쪽이 다른 쪽보다 빨리 실현될 때. "outrunning a proposal with a fork date"
moat(경쟁 우위의) 해자, 진입장벽 · 사업 전략에서 방어선을 비유. "don't build a moat out of 4337 plumbing"
fall out (of)~에서 자연스럽게 파생되다/도출되다 · 설계의 부산물로 생기는 결과. "stablecoin fees are what fall out"
AA계정 추상화(Account Abstraction) · 계정이 서명·수수료 지불·실행 방식을 프로그래밍 가능하게 만드는 개념. "Account abstraction is the project of erasing that split"
EOA외부 소유 계정(Externally Owned Account) · 개인키로 제어되는 기본 이더리움 계정, 스스로 실행은 못함. "An EOA can start transactions, but its rules are frozen"
ECDSA타원곡선 전자서명 알고리즘(Elliptic Curve Digital Signature Algorithm) · EOA가 쓰는 유일한 서명 방식을 가리킴. "one ECDSA key, one sequential nonce"
ERC-4337계정 추상화 표준(Ethereum Request for Comments 4337) · 컨트랙트로 AA를 흉내내는 현재 표준, 번들러·페이마스터를 도입. "ERC-4337 rebuilt a transaction system out of contracts"
EIP-7702이더리움 개선 제안 7702(Ethereum Improvement Proposal 7702) · EOA가 컨트랙트 코드를 빌려 쓰게 하는 제안. "EIP-7702 lets an EOA borrow contract code"
ACDE이더리움 실행계층 코어 개발자 콜(All Core Devs – Execution) · 프로토콜 변경을 논의하는 공식 회의체. "the ACDE readout, and the two kinds"
CFI → SFI포함 검토 → 포함 예정(Considered For Inclusion → Scheduled For Inclusion) · 이더리움 로드맵에서 제안의 채택 단계 전환. "the proposal went CFI → SFI"
FOCIL강제 포함 리스트(Fork-Choice enforced Inclusion List) · 검열 저항을 위한 별도 로드맵 제안, 8141과 같은 시기 배치 예정. "slotted for Hegotá (targeted 2027 Q2) alongside FOCIL"

← All Knowledge Notes · Workspace Index · Top ↑

ERC-8141

네이티브 계정 추상화 설명 페이지 — 이더리움 프로토콜 레벨 Frame Transactions.

읽기 전용 설명 페이지 — 지갑 불필요.

이 프로젝트의 애플리케이션 레벨 AA 데모(세션 키, 원자적 배치)가 스마트 컨트랙트와 위임으로 지금 하고 있는 일을, 프로토콜 네이티브 수준에서 미리 보여줍니다 — EIP-8141은 같은 속성을 이더리움의 기본 트랜잭션 포맷 자체로 옮기자는 제안입니다.

동작 방식

구조상 실제 동작하는 데모가 될 수 없습니다: EIP-8141은 트랜잭션 하나가 암묵적 호출 한 번이 아니라 프레임의 시퀀스(서명·수수료 인가를 담당하는 VERIFY 프레임, 이어지는 하나 이상의 EXECUTE 프레임)를 담는 새 트랜잭션 타입을 정의하지만, 아직 어떤 클라이언트나 RPC도 이 타입을 보낼 수 없습니다 — 네트워크에 없는 실행 계층 지원이 필요하기 때문입니다. 이 글을 쓰는 시점 기준 향후 포크에 "포함 검토 중"인 단계라, 라이브 데모가 아니라 다이어그램·설명 페이지로 남습니다.

ACDE 리드아웃, 그리고 두 종류의 "아니오" (2026-08-28)

이 제안과 EIP-8130 사이의 결론이 예정돼 있었고, 이 글을 쓰는 시점까지 공개된 리드아웃은 확인되지 않습니다. 그 공백에서 개발자 타임라인이 향한 곳이 쓸모 있는 부분입니다 — 논쟁이 내용이 아니라 무게로 옮겨갔습니다. 반복된 문장은 "방향은 맞는데 지금 단계에서 너무 무겁다" 였고, 이건 기술 반대가 아니라 일정 반대입니다.

이 구분은 붙들 값이 있습니다 — 밖에서 보면 똑같이 생겼는데 요구하는 대응이 정반대이기 때문입니다:

반대 실제로 하는 말 다음에 할 일
"이건 틀렸다" 설계가 목적을 달성하지 못한다 설계를 바꾼다
"이건 지금이 아니다" 설계는 맞고, 여기 넣기엔 크다 범위를 쪼갠다

두 번째를 듣고 재설계하면 헛일이고, 첫 번째를 듣고 미루기만 하면 더 나쁩니다. 회의실에서 물어야 할 것은 지금 받은 게 어느 쪽인가이고, 판별법은 대개 제안을 작게 만들었을 때도 그 반대가 살아남는가입니다.

검토 후 보완

기본 개념, 처음부터

이더리움에는 계정이 두 종류인데, 행동할 수 있는 쪽이 멍청합니다. EOA 는 트랜잭션을 시작할 수 있지만 규칙이 프로토콜에 얼어붙어 있습니다: ECDSA 키 하나, 순차 논스 하나, 수수료는 본인이 ETH 로, 트랜잭션당 호출 하나 — 키를 잃으면 계정을 잃습니다. 컨트랙트 계정은 완전히 프로그래머블하지만 아무것도 시작하지 못합니다. 계정 추상화(AA) 는 이 분리를 지우는 프로젝트입니다: 행동하는 계정이 프로그래머블하게 — 누가 서명하는지, 수수료를 어떻게 내는지, 트랜잭션 하나에 무엇이 담기는지를.

오늘의 AA 는 한 층 위에 지은 에뮬레이션입니다: ERC-4337 은 컨트랙트로 트랜잭션 시스템을 재건축했고(UserOperation, 번들러, EntryPoint), EIP-7702 는 EOA 가 컨트랙트 코드를 빌리게 합니다. 작동하지만 — 추가 행위자, 추가 가스, 추가 신뢰 표면이 대가입니다. EIP-8141 은 에뮬레이션을 끝내자는 제안입니다: 프레임으로 이루어진 새 베이스 트랜잭션 타입 — VERIFY 프레임 하나("인가 증명은 이것, 수수료는 이렇게") 뒤에 EXECUTE 프레임 하나 이상(호출들, 원자적으로: 전부 아니면 전무). 트랜잭션이 늘 갖고 있던 두 가지 일 — 허용됐음을 증명하기, 그다음 실행하기 — 이 포맷 자체의 명시적이고 분리된, 프로그래밍 가능한 부품이 됩니다.

같은 동작, 코드 세 세대

오늘 노드의 검사는 하드코딩이라 바꿀 수 없습니다:

assert(ecrecover(tx.sig) == tx.from);     // ECDSA 키 정확히 하나
assert(tx.nonce == account.nonce);        // 논스 정확히 하나
assert(balance[tx.from] >= gas * price);  // 본인이, ETH 로만
call(tx.to, tx.data);                     // 호출 정확히 하나

ERC-4337 은 이 검사를 컨트랙트 안에서 재연합니다 — EntryPoint.handleOps 가 UserOperation 들을 돌며 account.validateUserOp 그리고 account.execute 를 호출하고, 번들러가 배치를 나르고 페이마스터가 선택적으로 지불합니다. 홉 하나하나가 에뮬레이션 세금입니다.

EIP-8141 에서는 EntryPoint 가 흉내 내던 루프를 노드 자신이 돕니다:

tx = { type: FRAME_TX, frames: [
  { kind: VERIFY,  target: 내계정,
    input: { scheme: "p256-passkey", proof, feeToken: USDC } },
  { kind: EXECUTE, target: USDC, data: approve(dex, 100e6) },
  { kind: EXECUTE, target: dex,  data: swap(USDC, ETH, 100e6) },
]}

기능이 사는 곳은 계정 자신의 verify 코드입니다 — 네이티브 세션 키:

function verify(Proof p, Frame[] fs) external view returns (bool) {
    if (p.signer == owner) return checkSig(p);
    Session s = sessions[p.signer];              // 임시 키
    require(block.timestamp < s.expiry);         // …만료되고
    require(allCallsTo(fs, s.allowedContract));  // …이 앱만
    require(totalValue(fs) <= s.perTxLimit);     // …소액만
    return checkSig(p);
}

누가 행복해지나

누가 오늘의 고통 프레임 트랜잭션에서는
사용자 시드 문구 아니면 끝; 승인→스왑이 열린 승인을 남김; 먼저 ETH 필요 패스키가 네이티브 키; 승인+스왑 원자적; 수수료는 토큰이나 스폰서가
지갑 개발자 번들러+페이마스터 인프라 운영/임대 그 서비스들이 대부분 사라짐; 체인이 직접 검증
dApp/게임/에이전트 개발자 세션 키에 제공자별 스마트 지갑 스택 유계 위임이 베이스 레이어 기능
프로토콜 병렬 4337 멤풀; 공유 관문 EntryPoint 정본 멤풀 하나, 신뢰할 단일 컨트랙트 없음

구체적으로 개선되는 상황: 열린 승인 사고(EXECUTE 프레임 둘이면 스왑 없는 승인이 존재 불가능); ETH 없는 온보딩(VERIFY 안에서 스폰서가 지불); 키 분실 복구가 수탁자의 기능이 아니라 계정 로직이 되는 것; 포스트퀀텀 마이그레이션(서명 스킴이 포크할 프로토콜 상수가 아니라 업그레이드할 계정 코드가 됨); 에이전트 커머스(만료·허용 컨트랙트·건당 한도가 붙은 세션 키를 쥔 AI 에이전트 = 내가 고른 폭발 반경을 가진 위임).

정직한 비용 — ACDE 가 "너무 무겁다"고 한 이유의 대부분: VERIFY 프레임은 아무도 돈을 내기 전에 멤풀 유효성을 결정하는 임의 코드라서, 엄격한 가스 상한과 값싼 재검사가 없으면 무효 트랜잭션이 공짜 DoS 벡터가 됩니다.

"그럼 ERC-4337 은 일몰될 수 있겠네?" (jay, 2026-09-03)

방향은 맞고 시제가 틀렸습니다. 4337 은 처음부터 임시방편이었고 — 인슈라인먼트가 공공연한 최종 목표였으며, 8141 의 VERIFY/EXECUTE 분리는 본질적으로 validateUserOp/execute 의 포맷 승격입니다. 그러니 4337 은 죽는 게 아니라 흡수됩니다 — 컨트랙트는 비어 가도 개념은 살아남습니다. 하지만 일몰은 10년 단위의 감쇠입니다. 이유 넷: 이더리움에서는 아무것도 제거되지 않고(EntryPoint 는 불멸, 배포됐거나 counterfactual 인 수백만 스마트 계정 주소는 스스로 이주하지 않음); 네이티브 AA 경쟁이 미결이며(8141 대 8130 대 Tempo — 사용자를 가진 임시방편이 포크 날짜 없는 제안을 이김); L2 가 대칭을 깨고(4337 은 오늘 모든 EVM 체인에서 동일하게 작동하지만 네이티브 AA 는 체인마다 따로 — 크로스체인 지갑이 마지막 요새); 번들러/페이마스터 벤더들이 옛 레일을 지키는 대신 새 레일로 피벗해 자기를 낡게 만드는 일몰을 가속할 것이기 때문입니다. 전략으로서 — 4337 배관을 해자로 삼지 마라 — 는 이미 참입니다. 예보로서 — 트래픽 0 — 는 10년과 별표 하나를 붙이십시오.

진행 상황 (2026-09-08)

비탈릭의 9/6 Frames 업데이트가 진전을 알렸습니다: 8/27 콜에서 제안이 CFI → SFI(포함 검토 → 포함 예정)로 승격, FOCIL 과 나란히 Hegotá(2027 Q2 목표)에 배정됐습니다. SFI 는 배정이지 완료가 아닙니다 — 9/10 데브넷 선호목록 이후 볼 판별점은 8141 에 데브넷이 실제로 붙는가입니다. 프레이밍 둘. 헤드라인 '스테이블코인으로 가스 지불'은 설계가 아니라 결과입니다: 설계는 오늘 한 서명자에 묶인 세 역할 — 인가·가스 지불·실행 — 을 분리하는 것이고, 스테이블코인 수수료는 가스 지불이 VERIFY 안의 독립된 가닥이 되면 따라 나옵니다. 그리고 경쟁은 타이밍이 비대칭입니다: 경쟁안 EIP-8130 은 9월 중 Base 배포를 목표로 해서, L2 구현이 L1 표준보다 먼저 실물이 됩니다 — 사용자를 가진 임시방편이 또 한 번 포크 날짜 있는 제안을 앞지릅니다.

불변식 카드가 말하는 런타임 대 명세 논점이 여기 반대에도 적용됩니다: liquid-issuance-not-authorization 가, 인슈라인된 VERIFY 프레임이 왜 엄격히 가스 상한이 걸리고 값싸게 재검사돼야 하는지의 이유입니다 — 아무도 돈 내기 전에 도는 임의 유효성 코드는, 네트워크가 무조건 믿어 줄 수 없는 전제입니다.

관련 코드

# ERC-8141 — a transaction carries a sequence of frames instead of one implicit call:
# a VERIFY frame (signature/fee authorization) followed by one or more EXECUTE frames.
# Simulates the frame structure and runs it in sequence, aborting if VERIFY fails.

from dataclasses import dataclass, field
from typing import Callable


@dataclass
class Frame:
    kind: str  # "VERIFY" or "EXECUTE"
    description: str
    run: Callable[[dict], bool]


@dataclass
class FrameTransaction:
    frames: list[Frame] = field(default_factory=list)

    def execute(self, context: dict) -> bool:
        for frame in self.frames:
            print(f"  [{frame.kind}] {frame.description} ...", end=" ")
            ok = frame.run(context)
            print("OK" if ok else "FAILED")
            if frame.kind == "VERIFY" and not ok:
                print("  -> VERIFY frame failed: transaction aborted before any EXECUTE frame runs.")
                return False
            if frame.kind == "EXECUTE" and not ok:
                print("  -> EXECUTE frame failed: transaction reverts.")
                return False
        return True


def verify_signature_and_fee(ctx: dict) -> bool:
    return ctx.get("signature_valid", False) and ctx.get("balance", 0) >= ctx.get("max_fee", 0)


def execute_transfer(ctx: dict) -> bool:
    ctx["balance"] -= ctx["transfer_amount"]
    return ctx["balance"] >= 0


def execute_approve(ctx: dict) -> bool:
    ctx["allowance"] = ctx.get("allowance", 0) + ctx["approve_amount"]
    return True


def build_transaction() -> FrameTransaction:
    return FrameTransaction(frames=[
        Frame("VERIFY", "signature + fee authorization", verify_signature_and_fee),
        Frame("EXECUTE", "transfer 50 tokens", execute_transfer),
        Frame("EXECUTE", "approve spender for 20 tokens", execute_approve),
    ])


if __name__ == "__main__":
    print("EIP-8141 Frame Transaction — VERIFY then EXECUTE, EXECUTE, ...\n")

    print("Case 1: valid signature, sufficient balance")
    ctx = {"signature_valid": True, "balance": 100, "max_fee": 5, "transfer_amount": 50, "approve_amount": 20}
    ok = build_transaction().execute(ctx)
    print(f"Transaction succeeded: {ok}, final state: {ctx}\n")

    print("Case 2: invalid signature — VERIFY frame blocks all EXECUTE frames")
    ctx = {"signature_valid": False, "balance": 100, "max_fee": 5, "transfer_amount": 50, "approve_amount": 20}
    ok = build_transaction().execute(ctx)
    print(f"Transaction succeeded: {ok}")

Jayverse에서의 위치

  • Rabbit: 8141 진행 상황은 지켜보되 아직 설계를 바꾸지 않는다. 제안이 SFI 단계로 Hegotá(2027년 2분기 목표)를 향하는 지금, rabbit의 ERC-4337/EIP-7702 세션 키와 위임 스택을 단기 계획으로 유지한다. 네이티브 프레임 트랜잭션은 10년 단위 마이그레이션으로 지켜볼 대상이지 지금 AA 작업을 멈출 이유가 아니다.
  • Rabbit: 테스트넷이 생기면 세션 키를 VERIFY 프레임으로 시제작한다. 어떤 클라이언트든 공개 테스트넷에서 프레임 트랜잭션을 노출하면, 만료·허용 컨트랙트·트랜잭션당 한도를 갖는 최소 세션 키 위임을 VERIFY 프레임 로직으로 만든다. rabbit의 기존 위임 모델에 바로 대응되며 마이그레이션 경로를 일찍 검증하는 가장 싼 방법이다.
  • Devnet: 커스텀 validateUserOp류 검사도 같은 방식으로 가스를 제한한다. 제도화된 VERIFY 프레임이 무료 DoS 벡터가 되지 않으려면 엄격히 가스가 제한되고 값싸게 재검사 가능해야 한다는 원칙을, 지금 devnet에서 돌아가는 rabbit 자체 계정 검증 코드에도 그대로 적용한다.

핵심 표현

이 페이지의 영어 본문에서 배울 만한 단어와 표현, 뜻과 나온 자리.

Expression뜻 · 쓰이는 자리
considered for inclusion포함이 검토 중인 단계 · 제안이 아직 채택 전, 논의 대상일 뿐임을 표현. "it's only "considered for inclusion" in a future fork"
readout(회의 후) 결과 요약 보고 · 콜이 끝난 뒤 공개되는 결론 요약을 가리킴. "no public readout confirms an outcome"
sunset (동사)단계적으로 폐지하다, 퇴장시키다 · 오래된 시스템을 서서히 없앤다는 뜻. "Then ERC-4337 could be sunsetted?"
stopgap임시방편, 땜질용 조치 · 영구적 해법이 나올 때까지 쓰는 수단. "4337 was always the stopgap"
at the price of~을 대가로 치르고 · 이득을 얻는 동시에 지불하는 비용을 말할 때. "at the price of extra actors, extra gas"
dangling approval붕 뜬(미완료) 승인 상태 · approve만 되고 후속 실행은 안 된 상태. "leaves a dangling approval"
seed phrase or bust시드 문구 아니면 끝장 · "~or bust"는 양자택일을 강조하는 구어체. "Seed phrase or bust"
outrun~을 앞지르다, 추월하다 · 경쟁 구도에서 한쪽이 다른 쪽보다 빨리 실현될 때. "outrunning a proposal with a fork date"
moat(경쟁 우위의) 해자, 진입장벽 · 사업 전략에서 방어선을 비유. "don't build a moat out of 4337 plumbing"
fall out (of)~에서 자연스럽게 파생되다/도출되다 · 설계의 부산물로 생기는 결과. "stablecoin fees are what fall out"
AA계정 추상화(Account Abstraction) · 계정이 서명·수수료 지불·실행 방식을 프로그래밍 가능하게 만드는 개념. "Account abstraction is the project of erasing that split"
EOA외부 소유 계정(Externally Owned Account) · 개인키로 제어되는 기본 이더리움 계정, 스스로 실행은 못함. "An EOA can start transactions, but its rules are frozen"
ECDSA타원곡선 전자서명 알고리즘(Elliptic Curve Digital Signature Algorithm) · EOA가 쓰는 유일한 서명 방식을 가리킴. "one ECDSA key, one sequential nonce"
ERC-4337계정 추상화 표준(Ethereum Request for Comments 4337) · 컨트랙트로 AA를 흉내내는 현재 표준, 번들러·페이마스터를 도입. "ERC-4337 rebuilt a transaction system out of contracts"
EIP-7702이더리움 개선 제안 7702(Ethereum Improvement Proposal 7702) · EOA가 컨트랙트 코드를 빌려 쓰게 하는 제안. "EIP-7702 lets an EOA borrow contract code"
ACDE이더리움 실행계층 코어 개발자 콜(All Core Devs – Execution) · 프로토콜 변경을 논의하는 공식 회의체. "the ACDE readout, and the two kinds"
CFI → SFI포함 검토 → 포함 예정(Considered For Inclusion → Scheduled For Inclusion) · 이더리움 로드맵에서 제안의 채택 단계 전환. "the proposal went CFI → SFI"
FOCIL강제 포함 리스트(Fork-Choice enforced Inclusion List) · 검열 저항을 위한 별도 로드맵 제안, 8141과 같은 시기 배치 예정. "slotted for Hegotá (targeted 2027 Q2) alongside FOCIL"

← 전체 기술 노트 · 워크스페이스 인덱스 · 맨 위 ↑