All packages

uniswap-event-audit-blast-mainnet

ciyengar3
v0.0.1/2 downloads/Repository

Package ref

uniswap-event-audit-blast-mainnet@v0.0.1

Run package

CLI

Run counts_out from the command line.

substreams run uniswap-event-audit-blast-mainnet@v0.0.1 counts_out -e blast-mainnet
Authenticate by running substreams auth or directly on thegraph.market (see docs).

README

uniswap-event-audit

Per-block completeness digest of every event the pools package decodes, for a backend check that pulls it per chain and compares it with what landed in the warehouse. Stateless, no RPC, no sink and no dataset: the consumer streams the modules directly.

Modules

counts_out, digest_out and keys_out read the deployed uniswap-database-changes-pools-<chain> package's uniswap_v{2,3,4}:map_events (imported by URL, so the parent hashes are the live ones and the provider serves them from cache) and output flat DatabaseChanges, one emission per block.

ModuleTableRowsWhen
counts_outblock_digest_countsan all row every block (empty blocks included) and one per event type present: event_type, event_countevery tick; 3.7 MiB per 1,000 Base blocks
digest_outblock_digest_event_manifestthe same rows plus ordinals and block_indexes, roaring portable bitmaps (hex), empty on allover a range whose counts disagree
keys_outevent_keyone row per event: event_type, block_index, log_index, ordinal, transaction_index, tx_hash, pool_address (pool id for v4)over a flagged bucket only
final_head(a Clock)each block's clock, nothing else: no stores, no parentsonce per tick, to learn the provider's final block (below)
  • Every list in the three map_events outputs is an event type, named <version>_<list> (44 today). A test reads the Events messages from the protos, so a new list fails the build until it's covered here.
  • The three associated_evm_transaction types are transactions, not logs: their ordinals hold the tx begin ordinal and block_indexes the tx index.
  • Ordinals must fit 32 bits for the bitmaps; a larger one is an error.

Row envelope on every table: block_num, block_hash, timestamp, detail_level (BASE or EXTENDED), index, global_sequence ((block << 64) | row index, 39 digits) and ordering_key (the event type on counts and manifest rows, the pool on key rows). chain_id isn't emitted: the consumer tags it from the chain it streams.

These tables come from the pool-state package's digest_out / keys_out and match them field for field apart from ordering_key, without the pool-state sink's pool_changeset row (tests/digest.rs).

Build and publish

./scripts/build.sh <chain> <version>   # local/uniswap-labs-database-changes-event-audit-<chain>.spkg
make counts NETWORK=base START_BLOCK=51990000 ENDPOINT=base-mainnet.streamingfast.io:443

The build resolves the pools version the prod sink streams for the chain (infrastructure/config/sinks/prod, override with POOLS_VERSION or POOLS_SPKG), records it in each module's doc (the parents' spkg URL), and fails unless the parent map_events and store_pools hash exactly like the deployed pools package's. Publish with the "Build and Optionally Upload Database Changes Substreams Package" workflow, event-audit. The package is uniswap-event-audit-<chain>.

Cost, measured on Base (2026-10-02)

RequestProcessed blocksEgress
counts_out, 20 blocks, first request1,000 (one whole segment)62 KiB
counts_out, 1 block, segment already cached02.8 KiB
counts_out, 1,000 blocks, segment already cached03.7 MiB
digest_out, 20 blocks1,00099 KiB
keys_out, 20 blocks1,0001.5 MiB

A request is billed at least a whole 1,000-block segment the first time, and cached segments meter egress only, so the consumer should ask for 1,000-block-aligned ranges. Counts are about 3.8 KiB per Base block, more than the 1 KB estimate, since each of a block's ~8 rows carries the full envelope.

Finding the final block

There's no Substreams call that returns the final block, but every block message carries final_block_height. Request final_head from -1 (relative to the chain head) without final-blocks-only, read final_block_height from the first block and close the stream: 1 processed block and about half a second on Base (2026-10-02), with the provider's own idea of final (head − 200 on Base, against head − 604 for the RPC's finalized). Don't add final-blocks-only: -1 is relative to the chain head, so that waits for the head block to become final (~400 s on Base). And don't use counts_out for it: from -1 it pays the store catch-up since the segment started (1,400 processed blocks in the same test).

Modules

Execution graph

10 modules
map

final_head

Returns each block's clock. From -1 with final blocks only, the first block is the final head.

from #399405

Output

sf.substreams.v1.Clock

Inputs

sf.substreams.v1.Clock
Show 6 dependencies