Transaction receipt는 거래 실행 뒤 status, cumulative gas used, 생성된 logs와 이 로그들로 만든 2048비트 bloom을 담습니다. 각 log는 emitting contract address, 최대 네 개 topics와 data로 구성되며 event signature는 보통 topic0에 들어갑니다. Bloom은 주소와 각 topic의 해시에서 선택한 bit들을 세워 후보에 없다는 사실은 빠르게 판정하지만, 필요한 bit가 모두 켜져 있어도 다른 값들의 충돌일 수 있는 거짓 양성이 있습니다. 따라서 block header의 logsBloom으로 후보 block을 거른 뒤 receipt의 실제 address·topics를 다시 비교해야 이벤트 존재가 확정됩니다.
거래 결과는 영수증에 따로 남습니다
Ethereum transaction 본문에는 실행 뒤 생성될 event가 미리 들어 있지 않습니다. 실행 client는 transaction별 receipt에 success status, cumulativeGasUsed, logsBloom과 logs 목록을 기록합니다. Contract creation이면 contractAddress 같은 RPC 파생 필드도 볼 수 있지만 consensus receipt encoding과 JSON-RPC 응답 필드를 구분해야 합니다.
Status 1은 EVM 실행이 성공했다는 뜻이지 애플리케이션이 기대한 event가 반드시 발생했다는 보장은 아닙니다. Status 0인 실패 거래는 state changes와 logs가 revert됩니다. 내부 CALL이 실패했지만 바깥 코드가 이를 처리하고 계속했다면 전체 receipt는 성공일 수 있어 trace와 계약 로직을 함께 봅니다.
Bloom은 이벤트를 찾아 주는 색인이 아니라, 이 블록에는 찾는 주소나 topic이 없다는 후보 제외를 빠르게 해 주는 확률적 표지입니다.
JOBCOIN 해설

그림은 이 주제의 공통 개념을 단순화한 설명입니다. 아래 항목에서 이 글의 구체적인 조건과 예외를 함께 읽어보세요.
- 거래 결과는 영수증에 따로 남습니다
Ethereum transaction 본문에는 실행 뒤 생성될 event가 미리 들어 있지 않습니다.
- Log의 주소·topics·data는 역할이 다릅니다
LOG0부터 LOG4 opcode는 현재 실행 주소와 0~4개 topics, 임의 길이 data를 log entry로 만듭니다.
- Bloom은 세 쌍의 bit 위치를 검사합니다
주소 또는 topic을 Keccak-256하고 정해진 세 11-bit 값을 0~2047 위치로 사용해 bloom bits를 설정합니다.
AI로 제작한 개념도 · 실제 가격·거래 내역·통계가 아닙니다.
Log의 주소·topics·data는 역할이 다릅니다
LOG0부터 LOG4 opcode는 현재 실행 주소와 0~4개 topics, 임의 길이 data를 log entry로 만듭니다. Solidity event의 canonical signature hash가 보통 첫 topic이고 indexed 인수들이 뒤 topics에 들어갑니다. Indexed dynamic 값은 원문 대신 hash가 저장되므로 receipt만으로 문자열 원문을 복원할 수 없습니다.
Non-indexed 인수는 ABI encoding되어 data에 들어갑니다. Anonymous event는 signature topic을 생략할 수 있고 서로 다른 ABI가 같은 raw log를 다른 의미로 해석할 수 있습니다. Decoder는 address와 배포 시점의 code·ABI version을 고정하고 topic0 하나만으로 계약을 신뢰하지 않습니다.
| 자료 | 포함 정보 | 판정 한계 |
|---|---|---|
| Block header logsBloom | 블록 내 주소·topic bit 합집합 | 거짓 양성 가능 |
| Receipt logsBloom | 한 거래 로그 bit 합집합 | 실제 log 위치는 모름 |
| Log address | emit한 실행 주소 | 코드 의미는 ABI 필요 |
| Topics | 검색 가능한 indexed 값 | dynamic 원문은 hash |
| Data | non-indexed ABI bytes | 필터 topic 검색 대상 아님 |
Bloom은 세 쌍의 bit 위치를 검사합니다
주소 또는 topic을 Keccak-256하고 정해진 세 11-bit 값을 0~2047 위치로 사용해 bloom bits를 설정합니다. 여러 logs의 값은 OR로 합쳐집니다. 검색 값의 세 bit 중 하나라도 0이면 그 scope에는 값이 확실히 없지만 모두 1이어도 다른 여러 값이 우연히 같은 bits를 세웠을 수 있습니다.
예를 들어 인기 ERC-20 Transfer signature와 여러 contract 주소를 가진 block은 많은 bits가 켜집니다. 특정 token address와 account topic 조합이 bloom을 통과해도 실제 receipt logs에서 같은 한 entry가 모든 조건을 만족하는지 확인해야 합니다. 각 조건이 서로 다른 logs에서 bit를 제공할 수도 있습니다.
- Block hash·number와 receipt를 함께 저장합니다.
- Address와 topic filters로 bloom 후보를 좁힙니다.
- 후보 receipt의 실제 log entry를 다시 비교합니다.
- ABI version으로 indexed·data를 디코딩합니다.
- Reorg 시 removed block의 파생 상태를 역적용합니다.
개별 transaction gas used
Receipt의 cumulativeGasUsed는 해당 block에서 그 transaction까지 누적 사용량입니다. 개별 transaction gas used는 현재 receipt 누적값에서 직전 receipt 누적값을 빼거나 RPC가 제공하는 gasUsed 필드를 사용합니다. Gas limit 또는 effectiveGasPrice와도 다른 값입니다.
Typed transaction 이후 receipt도 type envelope에 들어갈 수 있습니다. Client API가 effectiveGasPrice, blob 관련 사용량 같은 확장 필드를 추가하더라도 모든 fork·chain에서 동일하다고 가정하지 않습니다. Raw receipt와 RPC schema의 client version을 기록합니다.
Reorg는 Chain reorganization으로 block이 빠지면
Latest block의 receipt는 canonical chain 후보에 포함됐다는 현재 관찰입니다. Chain reorganization으로 block이 빠지면 그 receipt와 logs도 canonical history에서 제거됩니다. Subscription API의 removed 표시를 처리하거나 저장한 block hash를 새 canonical hash와 대조해야 합니다.
입금이나 NFT 상태를 log 하나로 갱신할 때 transactionHash만 unique key로 쓰면 같은 transaction의 여러 logs를 덮어씁니다. chain id, block hash, transaction hash, log index를 식별자로 두고 safe·finalized 정책에 맞춰 provisional과 확정 상태를 분리합니다.
자주 묻는 질문
Logs bloom이 일치하면 이벤트가 반드시 있나요?
아닙니다. Hash bit 충돌로 거짓 양성이 가능해 실제 receipt의 address와 topics를 확인해야 합니다.
실패한 거래의 event도 receipt에 남나요?
Revert된 호출 frame의 logs는 폐기됩니다. 바깥 호출이 실패를 처리해 전체 성공한 경우에는 성공한 frame의 logs가 남을 수 있습니다.
Indexed string을 topic에서 원문으로 복원할 수 있나요?
Topic에는 dynamic 값의 hash가 들어가므로 원문 후보를 알고 검증할 수는 있어도 hash만으로 일반 복원할 수 없습니다.
더 깊이 읽기
본문에서 다룬 개념과 확인 절차를 다음 글에서 이어서 살펴보세요.



