Workspace IndexDev Notes › A successful receipt is not settlement

#32PoC

A successful receipt is not settlement

status: 1 proves execution in one block; it does not prove that the block will remain canonical. Payment products need included, safe, finalized, and reorged states instead of one paid boolean.

Implement the detected → included → safe → finalized (+ reorged) state machine against a local fork, replay a removed receipt, and watch each fulfillment tier react — the reversible tier rolls back, the irreversible tier never starts early.

Why

The RPC call succeeds before the business promise is safe. This is where chain finality becomes product policy: cheap reversible goods can accept risk; expensive irreversible delivery cannot.

A payment system that stores only paid = true cannot represent a reorg. Product fulfillment and chain confidence must advance separately: a reversible benefit can be granted early, while an irreversible shipment waits.

How it works

Build a reorg-aware payment state machine, replay a removed receipt on a local fork, and verify that reversible fulfillment rolls back while irreversible fulfillment waits for the configured confidence level.

PoC

Implement detected → included → safe → finalized plus reorged. Replay a removed receipt on a local fork and prove that provisional fulfillment is withdrawn or retried, while high-value fulfillment never starts before its configured threshold.

Chain state Product action
Included/latest Acknowledge and reserve
Safe Low-risk fulfillment
Finalized Irreversible settlement
Reorged Rollback, retry, or request payment

Reference: Ethereum JSON-RPC block tags.

Review clarification

Card rails already run this machine — crypto hid it behind a boolean

Traditional card processing is authorize → capture → settle, with a chargeback window measured in months. This card's reorged state is the chargeback, rediscovered. Crypto marketed "no chargebacks," but until finality a payment is probabilistic — so any honest payment product converges on the same tiered shape card rails use. The table's real move is pairing each chain state with a product action: that is risk pricing, not plumbing.

The tiers have numbers, and they are chain-specific

On Ethereum L1: included ≈ 12 seconds, safe (justified) ≈ 6.4 minutes, finalized ≈ 12.8 minutes. On an L2 the same words mean different clocks — sequencer preconfirmation in milliseconds, L1 posting, L1 finality — which is exactly l2-finality-three-clocks. So "which tier ships the goods" cannot be one global setting; it is a per-chain policy table, and the PoC should record one per target chain.

The machine is missing a sixth state, and it prevents false alarms

After a reorg the removed transaction usually re-lands automatically — it returns to the mempool and is mined into the replacement chain. So reorged → rollback + "payment failed" email is the false-positive trap. The honest machine is six states: reorged → pending-reinclusion → (re-included | failed after timeout). Roll back the benefit immediately; delay the customer-facing verdict through a grace window.

Test mechanics, and where Jayverse plugs in

Locally this is very runnable: anvil's snapshot/revert (or anvil_reorg) mines the payment, reverts, re-mines without it — then assert the indexer notices the receipt vanish. ponder-reorg-indexer is this card's infrastructure half: "detected the removal" actually happens in the indexer. Applications in this catalogue's own plans: a Verex bet credits at included (a reversible ledger entry), withdrawals wait for finalized, and x402-settlement-retry shares the boundary — a facilitator's "settled" response is also a receipt, and this card asks the follow-up: settled at which tier? Pairs naturally with a local supersim L2 lab: same fork, three clocks disagreeing, one state machine reacting.

← All Dev Notes · Workspace Index · Top ↑

성공한 receipt 는 정산이 아니다

status: 1 은 어느 한 블록 안에서 실행이 성공했다는 증명이지, 그 블록이 정식 체인에 남는다는 증명이 아닙니다. 결제 제품에는 paid 불리언 하나가 아니라 included·safe·finalized·reorged 상태가 필요합니다.

로컬 포크 위에 detected → included → safe → finalized (+ reorged) 상태 머신을 구현하고, 제거된 receipt 를 재생하면서 각 이행 단계의 반응을 확인합니다 — 되돌릴 수 있는 단계는 롤백되고, 비가역 단계는 애초에 일찍 시작되지 않아야 합니다.

RPC 호출은 비즈니스 약속이 안전해지기 전에 성공합니다. 체인 파이널리티가 제품 정책이 되는 지점이 바로 여기입니다: 싸고 되돌릴 수 있는 상품은 위험을 감수할 수 있지만, 비싸고 비가역적인 배송은 그럴 수 없습니다.

paid = true 만 저장하는 결제 시스템은 리오그를 표현할 수 없습니다. 제품 이행과 체인 확신은 따로 전진해야 합니다: 되돌릴 수 있는 혜택은 일찍 줄 수 있고, 비가역적인 출고는 기다립니다.

동작 방식

리오그를 아는 결제 상태 머신을 만들고, 로컬 포크에서 제거된 receipt 를 재생하며, 되돌릴 수 있는 이행은 롤백되고 비가역 이행은 설정된 신뢰 수준까지 기다리는지 검증합니다.

PoC

detected → included → safe → finalizedreorged 를 더해 구현합니다. 로컬 포크에서 제거된 receipt 를 재생해, 잠정 이행은 회수되거나 재시도되고 고가치 이행은 설정된 임계값 전에 시작되지 않음을 증명합니다.

체인 상태 제품 행동
Included/latest 접수하고 예약
Safe 저위험 이행
Finalized 비가역 정산
Reorged 롤백, 재시도, 또는 재결제 요청

참고: Ethereum JSON-RPC 블록 태그.

검토 후 보완

카드 결제 레일은 이미 이 머신을 돌린다 — 크립토가 불리언 뒤에 숨겼을 뿐

전통 카드 결제는 승인 → 매입 → 정산이고, 차지백 기간은 개월 단위입니다. 이 카드의 reorged 상태가 재발견된 차지백입니다. 크립토는 "차지백 없음"을 마케팅했지만 파이널리티 전까지 결제는 확률적입니다 — 그래서 정직한 결제 제품은 카드 레일과 같은 계층 구조로 수렴합니다. 이 표의 진짜 수는 체인 상태마다 제품 행동을 짝지은 것입니다: 배관이 아니라 리스크 프라이싱입니다.

계층에는 숫자가 있고, 체인마다 다르다

이더리움 L1: included ≈ 12초, safe(justified) ≈ 6.4분, finalized ≈ 12.8분. L2 에서는 같은 단어가 다른 시계를 뜻합니다 — 밀리초의 시퀀서 사전확인, L1 게시, L1 파이널리티 — 정확히 l2-finality-three-clocks입니다. 따라서 "몇 층에서 상품을 발송하나"는 전역 설정 하나일 수 없고 체인별 정책 표이며, PoC 는 대상 체인마다 하나씩 기록해야 합니다.

머신에 여섯째 상태가 빠져 있고, 그것이 오경보를 막는다

리오그 후 제거된 트랜잭션은 대개 자동으로 다시 실립니다 — 멤풀로 돌아가 대체 체인에 채굴됩니다. 그래서 reorged → 롤백 + "결제 실패" 이메일은 오탐 함정입니다. 정직한 머신은 여섯 상태입니다: reorged → 재포함 대기 → (재포함 | 타임아웃 후 실패). 혜택은 즉시 롤백하되, 고객에게 보이는 판정은 유예 기간을 거칠 것.

시험 방법, 그리고 Jayverse 가 꽂히는 자리

로컬에서 아주 잘 돌아갑니다: anvil 의 snapshot/revert(또는 anvil_reorg)로 결제를 채굴 → 되감기 → 그 트랜잭션 없이 재채굴 — 그리고 인덱서가 receipt 소멸을 알아채는지 확인합니다. ponder-reorg-indexer가 이 카드의 인프라 절반입니다: "제거 감지"는 실제로 인덱서에서 일어납니다. 이 목록 자체의 계획에 적용하면: Verex 베팅은 included에서 적립(되돌릴 수 있는 장부 항목), 출금은 finalized 대기, 그리고 x402-settlement-retry가 같은 경계를 공유합니다 — facilitator 의 "정산됨" 응답도 하나의 receipt 이고, 이 카드는 후속 질문을 던집니다: 몇 층에서 정산됐는가? 로컬 supersim L2 실험실과 자연스럽게 짝이 됩니다: 같은 포크, 어긋나는 세 시계, 반응하는 상태 머신 하나.

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