Try it Live
Run EventLog examples in the interactive playground
Filter Semantics
Null Wildcard
null at any position matches any topic value:
Copy
Ask AI
import { EventLog, Hash } from 'tevm';
const TRANSFER_SIG = Hash('0xddf252ad...');
// Match Transfer events with any from/to addresses
const matches = log.matchesTopics([
TRANSFER_SIG, // topic0 must be Transfer signature
null, // topic1 can be any address
null, // topic2 can be any address
]);
Single Hash Match
Specific hash must match exactly at that position:Copy
Ask AI
import { EventLog, Hash } from 'tevm';
const TRANSFER_SIG = Hash('0xddf252ad...');
const userHash = Hash('0x000000000000000000000000a1b2c3d4...');
// Match Transfer events TO specific user
const matches = log.matchesTopics([
TRANSFER_SIG, // Exact signature
null, // from: any
userHash, // to: specific user
]);
Array of Hashes (OR Logic)
Matches if log topic equals ANY hash in the array:Copy
Ask AI
import { EventLog, Hash } from 'tevm';
const TRANSFER_SIG = Hash('0xddf252ad...');
const APPROVAL_SIG = Hash('0x8c5be1e5...');
// Match Transfer OR Approval events
const matches = log.matchesTopics([
[TRANSFER_SIG, APPROVAL_SIG], // topic0 can be either
]);
Empty Filter Array
Empty filter matches all logs:Copy
Ask AI
import { EventLog } from 'tevm';
// Matches all logs
const matches = log.matchesTopics([]);
console.log(matches); // true
Usage Patterns
ERC-20 Transfer Filtering
Copy
Ask AI
import { EventLog, Address, Hash } from 'tevm';
// Transfer(address indexed from, address indexed to, uint256 value)
const TRANSFER_SIG = Hash('0xddf252ad...');
const userAddress = Address('0xa1b2c3d4...');
const userHash = Hash(
new Uint8Array([...new Uint8Array(12).fill(0), ...userAddress])
);
// All transfers FROM user
const outgoing = allLogs.filter(log =>
log.matchesTopics([TRANSFER_SIG, userHash, null])
);
// All transfers TO user
const incoming = allLogs.filter(log =>
log.matchesTopics([TRANSFER_SIG, null, userHash])
);
// All transfers involving user (from OR to)
const userTransfers = allLogs.filter(log =>
log.matchesTopics([TRANSFER_SIG, userHash, null]) ||
log.matchesTopics([TRANSFER_SIG, null, userHash])
);
console.log(`Outgoing: ${outgoing.length}`);
console.log(`Incoming: ${incoming.length}`);
console.log(`Total: ${userTransfers.length}`);
Multiple Event Types
Copy
Ask AI
import { EventLog, Hash } from 'tevm';
const TRANSFER_SIG = Hash('0xddf252ad...');
const APPROVAL_SIG = Hash('0x8c5be1e5...');
const SWAP_SIG = Hash('0xd78ad95f...');
// Match any of these event types
const relevantLogs = allLogs.filter(log =>
log.matchesTopics([[TRANSFER_SIG, APPROVAL_SIG, SWAP_SIG]])
);
console.log(`Found ${relevantLogs.length} relevant events`);
Intra-Group Transfers
Copy
Ask AI
import { EventLog, Hash } from 'tevm';
const TRANSFER_SIG = Hash('0xddf252ad...');
// Addresses in the group
const groupHashes = [
Hash('0x000...addr1'),
Hash('0x000...addr2'),
Hash('0x000...addr3'),
];
// Transfers between any group members
const intraGroupTransfers = allLogs.filter(log =>
log.matchesTopics([
TRANSFER_SIG,
groupHashes, // from: any group member
groupHashes, // to: any group member
])
);
console.log(`Intra-group transfers: ${intraGroupTransfers.length}`);
DEX Swap Monitoring
Copy
Ask AI
import { EventLog, Hash } from 'tevm';
// Uniswap V2 Swap(address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to)
const SWAP_SIG = Hash('0xd78ad95f...');
const routerHash = Hash('0x000...router');
// Swaps initiated by router
const routerSwaps = allLogs.filter(log =>
log.matchesTopics([SWAP_SIG, routerHash])
);
NFT Transfer Tracking
Copy
Ask AI
import { EventLog, Hash } from 'tevm';
// Transfer(address indexed from, address indexed to, uint256 indexed tokenId)
const TRANSFER_SIG = Hash('0xddf252ad...');
const zeroHash = Hash('0x0000000000000000000000000000000000000000000000000000000000000000');
// NFT mints (from zero address)
const mints = allLogs.filter(log =>
log.matchesTopics([TRANSFER_SIG, zeroHash, null])
);
// NFT burns (to zero address)
const burns = allLogs.filter(log =>
log.matchesTopics([TRANSFER_SIG, null, zeroHash])
);
console.log(`Mints: ${mints.length}`);
console.log(`Burns: ${burns.length}`);
Anonymous Event Handling
Copy
Ask AI
import { EventLog } from 'tevm';
// Anonymous events: topic0 is first indexed param, not signature
const anonymousLog = EventLog({
address: contractAddress,
topics: [param1Hash, param2Hash, param3Hash],
data: Bytes(),
});
// Match by first indexed parameter (NOT signature)
const matches = anonymousLog.matchesTopics([
param1Hash, // topic0 is first param
null, // topic1 is second param (any)
param3Hash, // topic2 is third param
]);
Advanced Patterns
Complex Boolean Logic
Copy
Ask AI
import { EventLog, Hash } from 'tevm';
const TRANSFER_SIG = Hash('0xddf252ad...');
const user1Hash = Hash('0x000...user1');
const user2Hash = Hash('0x000...user2');
const user3Hash = Hash('0x000...user3');
// (from:user1 AND to:user2) OR (from:user2 AND to:user3)
const complexFilter = allLogs.filter(log =>
(log.matchesTopics([TRANSFER_SIG, user1Hash, user2Hash]) ||
log.matchesTopics([TRANSFER_SIG, user2Hash, user3Hash]))
);
Partial Filter (Fewer Topics)
Filter can have fewer topics than log:Copy
Ask AI
import { EventLog, Hash } from 'tevm';
const log = EventLog({
address: contractAddress,
topics: [topic0, topic1, topic2, topic3], // 4 topics
data: Bytes(),
});
// Match only first 2 topics
const matches = log.matchesTopics([topic0, topic1]);
console.log(matches); // true (remaining topics ignored)
Empty Topics Check
Copy
Ask AI
import { EventLog } from 'tevm';
const log = EventLog({
address: contractAddress,
topics: [], // No topics
data: Bytes(),
});
// Filter with topics fails
const matches1 = log.matchesTopics([Hash('0x...')]);
console.log(matches1); // false
// Empty filter matches
const matches2 = log.matchesTopics([]);
console.log(matches2); // true
Performance
Uses constant-time hash comparison for security:Copy
Ask AI
import { EventLog } from 'tevm';
// Comparison time doesn't leak which topics match
const matches = log.matchesTopics([sig, null, userHash]);
filterLogs for optimized batch filtering:
Copy
Ask AI
import { EventLog } from 'tevm';
// Efficient batch filtering
const filtered = EventLog.filterLogs(allLogs, {
topics: [TRANSFER_SIG, null, userHash],
});
See Also
- matchesAddress - Filter by address
- matchesFilter - Complete filter matching
- filterLogs - Batch filtering
- Fundamentals - Topic structure and indexing

