Try it Live
Run EventLog examples in the interactive playground
Chain Reorganizations
Chain reorganizations occur when a different chain becomes canonical, invalidating blocks and their logs:Copy
Ask AI
import { EventLog, Address, Hash } from 'tevm';
// Original log (in canonical chain)
const log = EventLog({
address: tokenAddress,
topics: [TRANSFER_SIG, fromHash, toHash],
data: valueData,
blockNumber: 18000000n,
blockHash: Hash('0xabc...'),
removed: false,
});
// After reorg, RPC marks log as removed
const updatedLog = EventLog({
...log,
removed: true,
});
console.log(log.isRemoved()); // false
console.log(updatedLog.isRemoved()); // true
Usage Patterns
Filtering Active Logs
Copy
Ask AI
import { EventLog } from 'tevm';
// Remove invalidated logs
const activeLogs = allLogs.filter(log => !log.isRemoved());
console.log(`Active: ${activeLogs.length} of ${allLogs.length}`);
Detecting Reorgs
Copy
Ask AI
import { EventLog } from 'tevm';
function detectReorg(newLogs: EventLog[]): void {
const removed = newLogs.filter(log => log.isRemoved());
if (removed.length > 0) {
console.log(`⚠️ Chain reorg detected: ${removed.length} logs invalidated`);
for (const log of removed) {
console.log(` Block ${log.blockNumber}, Log ${log.logIndex}`);
console.log(` Address: ${Address.toHex(log.address)}`);
}
// Reprocess affected blocks
const affectedBlocks = new Set(
removed.map(log => log.blockNumber).filter(n => n !== undefined)
);
for (const blockNum of affectedBlocks) {
console.log(` Reprocessing block ${blockNum}`);
// Re-fetch and reprocess
}
}
}
detectReorg(latestLogs);
Comparing Log Sets
Copy
Ask AI
import { EventLog } from 'tevm';
function compareLogSets(oldLogs: EventLog[], newLogs: EventLog[]): void {
const oldActive = oldLogs.filter(log => !log.isRemoved());
const newActive = newLogs.filter(log => !log.isRemoved());
const newRemoved = newLogs.filter(log => log.isRemoved());
console.log(`Old active: ${oldActive.length}`);
console.log(`New active: ${newActive.length}`);
console.log(`Newly removed: ${newRemoved.length}`);
if (newRemoved.length > 0) {
console.log('⚠️ Reorg detected!');
}
}
Processing with Reorg Handling
Copy
Ask AI
import { EventLog } from 'tevm';
function processLogs(logs: EventLog[]): void {
for (const log of logs) {
if (log.isRemoved()) {
console.log(`Skipping removed log at block ${log.blockNumber}`);
continue;
}
// Process active log
const sig = log.getTopic0();
// ... decode and handle event
}
}
processLogs(allLogs);
Reorg-Aware Database
Copy
Ask AI
import { EventLog } from 'tevm';
class LogDatabase {
private logs: Map<string, EventLog> = new Map();
insert(log: EventLog): void {
if (log.isRemoved()) {
console.log('Refusing to insert removed log');
return;
}
const key = this.makeKey(log);
this.logs.set(key, log);
}
update(log: EventLog): void {
const key = this.makeKey(log);
if (log.isRemoved()) {
console.log(`Removing invalidated log: ${key}`);
this.logs.delete(key);
} else {
this.logs.set(key, log);
}
}
private makeKey(log: EventLog): string {
return `${log.blockNumber}-${log.logIndex}`;
}
}
const db = new LogDatabase();
// Initial insert
db.insert(log);
// After reorg
const updatedLog = { ...log, removed: true };
db.update(updatedLog); // Removes from database
Transaction Receipt Processing
Copy
Ask AI
import { EventLog } from 'tevm';
function processReceipt(receipt: TransactionReceipt): void {
const logs = receipt.logs.map(EventLog.from);
const activeLogs = logs.filter(log => !log.isRemoved());
if (activeLogs.length < logs.length) {
console.log(`⚠️ ${logs.length - activeLogs.length} logs removed by reorg`);
}
// Process only active logs
for (const log of activeLogs) {
// ... handle event
}
}
Default Behavior
Logs withoutremoved field default to active (not removed):
Copy
Ask AI
import { EventLog, Address, Hash } from 'tevm';
const log = EventLog({
address: Address('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2'),
topics: [Hash('0xddf252ad...')],
data: Bytes(),
// No removed field
});
console.log(log.removed); // undefined
console.log(log.isRemoved()); // false (treats undefined as false)
RPC Integration
eth_getLogs and receipt endpoints include removed flag:
Copy
Ask AI
import { EventLog, Address, Hash, Hex } from 'tevm';
// RPC response includes removed flag
const rpcLog = {
address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2',
topics: ['0xddf252ad...'],
data: '0x0000...0001',
blockNumber: '0x112a880',
removed: true, // Set by RPC after reorg
};
const log = EventLog({
address: Address(rpcLog.address),
topics: rpcLog.topics.map(Hash.fromHex),
data: Hex.toBytes(rpcLog.data),
blockNumber: BigInt(rpcLog.blockNumber),
removed: rpcLog.removed,
});
if (log.isRemoved()) {
console.log('Log invalidated by chain reorganization');
}
See Also
- wasRemoved - Alias for isRemoved
- sortLogs - Sort logs chronologically
- filterLogs - Filter logs (can exclude removed)
- Fundamentals - Chain reorganizations

