Conventions that apply everywhere
- Hashes and addresses are complete. Never truncated, anywhere. You should
be able to match them by eye against a log. - Null means unknown. Never zero, never “none”. A null price means the
oracle family isn’t replicated; a null health factor means no debt. - Bars are stored unscaled; decimals apply at read.
- Values described as USD are in oracle base units (1e8 = $1) inside the
warehouse and converted at the edge.
The catalogue
Every dataset on the Data Downloads form is a section
below, under its warehouse table, with every column the export form offers.
The catalogue keys are raw_logs, price_bars, aave_liquidations,
aave_health, compound_absorbs, morpho_liquidations, maker_vaults and
events; the same keys name a dataset on the API (GET /datasets,
POST /datasets/{key}/requests) and in a derived citation. A test checks that
every key in the catalogue has its section here, and that every column the
form offers is documented.
Every warehouse table carries chain (eth_mainnet today) and, where more
than one deployment writes to it, protocol.
Event logs: eth_logs_wide
The raw table: every log the chain emitted, one row per log, with the
transaction it came from. This is what the derived tables are computed from,
and the dataset to export when no derived table asks your question. Filter by
event signature (topic0), by an address in any role (sender, recipient,
emitter) and by block or date range; an unbounded export is refused by the
row cap rather than attempted.
| Column | Meaning |
|---|---|
block_number |
the block the log is in |
block_timestamp |
the block’s timestamp, UTC |
tx_hash |
the transaction, complete |
transaction_index |
the transaction’s position in the block |
from_address / to_address |
the transaction’s sender and recipient (the called contract, or the recipient of a plain transfer) |
value |
ETH sent with the transaction, wei, unscaled |
log_emitter |
the contract that emitted the log |
topic0 |
the event signature hash; decoded events says how it is read |
topic1 / topic2 / topic3 |
the indexed arguments, as 32-byte hex; empty when the event has fewer |
data |
the non-indexed arguments, ABI-encoded hex |
log_index |
the log’s position in the block |
Addresses are stored as hex without 0x, uppercase, as ClickHouse’s hex()
writes them; the export form accepts either casing.
Refresh: continuous. The bulk ingester on the warehouse host appends blocks
as they finalise, 64 confirmations (about 13 minutes) behind the head, and
never revisits a block; the last few minutes live in the head table the
explorer reads, not in this export. Ingest lag is on
the status page.
Price bars: dfrds_price_bars
One row per pool-hour, for every pool the chain has, not only tracked
markets. The catalogue entry is checked against this table’s CREATE TABLE
on every test run, so a column named here is a column you can export.
| Column | Meaning |
|---|---|
chain / architecture |
eth_mainnet; cpmm (Uniswap V2-style, priced from Sync reserves), clamm (V3-style, from sqrtPriceX96), stableswap (Curve plain pools: the replayed get_dy for one unit), weighted (Balancer V2: the spot price from replayed balances and registered weights), batch_auction (CoW Protocol: realised clearing prices per pair) or consolidated (one row per pair-hour: the live venues’ closes weighted by volume; see the methodology) |
pool |
pool address, uppercase hex with no 0x, as ClickHouse’s hex() writes it. The export form accepts either casing. For consolidated rows it is the pair key PAIR_<token0>_<token1>, addresses in address order; for batch_auction rows it is <SETTLEMENT>_<token0>_<token1>, the settlement contract and the pair |
hour |
bucket start, UTC |
open / high / low / close |
price within the bucket, token0 per token1, unscaled. token0 and token1 are the pool’s first two tokens (stableswap coins 0 and 1, the Vault’s first two registered tokens for weighted), or the pair in address order for batch_auction |
volume0 |
summed trade amounts in the bucket, token0 units, unscaled |
trades |
events folded into the bar: Syncs for cpmm, Swaps for clamm and weighted, TokenExchanges for stableswap, Trades for batch_auction. A stableswap or weighted bar also carries the quotes after liquidity events, which are not trades |
max_block |
the highest block the bar has seen; the refresh’s watermark, and the version a recompute replaces |
Scaling: price × 10^(decimals1 − decimals0), volume ÷ 10^decimals0, which is
what the platform’s own charts do.
Refresh: every 15 minutes (RefreshPriceBarsJob, block-watermark increments,
new pools get their full history ten per run), with the consolidated rows
recomputed five minutes behind each refresh.
Aave health panel: dfrds_aave_health
| Column | Meaning |
|---|---|
block |
the snapshot block |
user |
account address |
total_collateral / total_debt |
oracle base units (1e8 = $1) |
ltv_bps / liquidation_threshold_bps |
value-weighted, in basis points |
health_factor |
wad (1e18); uint256 max means no debt |
collateral_assets / debt_assets |
how many reserves the position touches |
skip_reason |
why the account was not computed; empty when it was |
cadence |
monthly (the longitudinal panel, one cross-section per ~30 days of blocks) or daily (one compact row per account at the last block of a UTC day). Filter on it: a query that groups by block across both would put points a day apart next to points a month apart |
day |
the calendar day the cross-section stands for, and the table’s partition key on a table created since P3.6. 1970-01-01 on rows written before the column existed, which are all monthly |
Refresh: the monthly cross-section is checked weekly (Aave Sundays, Spark
Saturdays, 03:00 UTC) and built once the chain is ~30 days of blocks past the
last one; the daily cross-section is built every morning at 07:00 UTC for
every deployment. clickhouse:aave_health:setup creates the table, or adds
the two columns to one that predates them (its partitioning cannot be changed
in place). Never a materialised view on the ingest table. See
health factors.
Both Aave-model tables carry chain and protocol. protocol is the
deployment key (aave_v3, spark), and every query must filter on it:
the same asset is a reserve in several deployments with different token
addresses.
Aave liquidations: dfrds_aave_liquidations
| Column | Meaning |
|---|---|
block / block_timestamp |
the block of the LiquidationCall event and its timestamp, UTC |
tx_hash / log_index |
the transaction, complete, and the log’s position in the block |
borrower / liquidator |
the account liquidated and the account that repaid |
collateral_asset / collateral_symbol |
the reserve seized, by address and by the symbol on record |
debt_asset / debt_symbol |
the reserve repaid, by address and by the symbol on record |
debt_repaid / collateral_seized |
scaled by token decimals |
debt_price / collateral_price |
oracle price at that block, 1e8 |
debt_value_usd / collateral_value_usd |
USD; null when unpriced |
realized_bonus_pct |
seized value over repaid value, minus one |
configured_bonus_pct |
governance’s bonus for that reserve at that block |
receive_atoken |
liquidator took aTokens rather than the underlying |
price_note |
why a price is missing |
Refresh: nightly (Aave V3 03:15 UTC, Spark 03:35), resuming from the newest
stored block and stopping 64 blocks behind the head. Rows replace on
(chain, protocol, block, tx_hash, log_index), so an overlapping re-run is
harmless. Last runs are on the admin ClickHouse page.
Compound v3 absorptions: dfrds_compound_absorbs
One row per absorption event, and Comet emits two kinds: the debt it took on
and each collateral it seized. kind tells them apart, so a query that
doesn’t filter on kind double-counts.
| Column | Meaning |
|---|---|
block / block_timestamp |
the block of the event and its timestamp, UTC |
tx_hash / log_index |
the transaction, complete, and the log’s position in the block |
kind |
debt (the account’s debt, absorbed by the protocol) or collateral (one asset seized) |
market |
the Comet proxy address; base_symbol is its borrowable base asset |
absorber |
who triggered the absorption and took the reward: not a liquidator repaying debt |
borrower |
the account absorbed |
asset |
the base token on a debt row, the seized token on a collateral row |
amount_raw |
unscaled, in asset’s own decimals |
usd_value |
Compound’s own figure from its price feeds, not ours |
usd_value is the protocol’s accounting, published in the event. That is
different provenance from the Aave tables above, where the oracle is replicated
and validated: see Compound v3.
Refresh: nightly at 04:15 UTC, resuming from the newest stored block and
stopping 64 blocks behind the head.
Maker vaults: dfrds_maker_vaults
One dated cross-section per build, like the Aave health panel, so the table
is a longitudinal panel rather than a snapshot that overwrites itself.
Protocol-native units: this is the Vat’s own arithmetic, not a
translation of it into health factors.
| Column | Meaning |
|---|---|
block |
the snapshot block |
ilk / urn |
collateral type (ETH-A) and the vault’s address |
ink |
locked collateral, wad. 0 when the ilk’s ink is bookkeeping rather than a balance (the PSMs), with the reason in skip_reason |
art |
normalised debt, wad; the debt is art × rate / RAY |
rate |
the ilk’s accumulated rate, ray |
spot |
collateral price with the liquidation ratio already folded in, ray |
collateral_usd / debt_usd |
ink × spot and art × rate, converted; 0 when unknown, and skip_reason says so |
safety |
ink × spot over art × rate: 1.0 at the liquidation boundary, not the collateralisation ratio people quote. Null when it cannot be computed |
skip_reason |
not_a_balance, sentinel_ink, no_rate or no_spot; empty when the vault was computed |
Debt and collateral fail separately: art × rate is real for every ilk,
including the ones whose ink is bookkeeping, so a vault can have a debt
figure and no collateral figure. protocol is maker.
Refresh: checked weekly (Mondays 03:00 UTC), building a new cross-section
once the chain is ~30 days of blocks past the last one.
Liquidation health: aave_liquidation_healths
| Column | Meaning |
|---|---|
health_factor_before |
the position replayed at the block before the liquidation |
health_factor_after |
derived from the event’s own amounts; null when the debt was fully repaid |
collateral_threshold_bps |
the seized asset’s liquidation threshold, not the position average |
aave_flash_loan |
an Aave flash loan funded the repayment; false means “no Aave flash loan”, not “no leverage” |
swaps_in_tx |
V2 + V3 swaps in the liquidating transaction: the collateral dump |
status / reason |
computed, or why the position could not be replayed |
Gas and priority fee are absent by design: the warehouse ingests logs, not
receipts.
Event registry: chain_events
| Column | Meaning |
|---|---|
id |
the event’s id, stable across imports: cite it, not the title |
title / category |
what happened, in a line, and its kind: exploit, depeg, regulation, upgrade, adoption or other |
protocol / classification / technique |
the protocol involved, the source’s class of incident and the technique used, as the source records them; blank when it does not |
occurred_on / ended_on |
date; ended_on set only for episodes |
amount_usd / returned_usd |
as the source publishes them; null if unpublished |
chains |
chain names as the source records them |
tx_hashes / addresses |
on-chain artifacts, added by curation. Complete or refused — a truncated hash is rejected at save, because it cannot be matched against anything and looks as though it can |
anchors_verified_at |
when those hashes were last confirmed to exist in the warehouse. Null means nobody checked, which is not the same as having nothing to check |
severity |
1–5; see ChainEvent::SEVERITY for the written scale |
severity_basis |
derived (computed from loss, recovery and duration) or judged (a curator’s call). Both are scores; they are not the same claim |
scored_by_id / scored_at |
who applied the severity, and when |
reference_prices |
labelled levels for a chart: pre, trough, recovery, each {label, value, on} |
source_name / source_url / source_ref |
provenance; an event cannot exist without one. DeFiLlama (weekly hacks import, ref name-date), DFRDS depeg detector (daily, ref STABLE/QUOTE@block of the first off-peg bar), Governor (on-chain) (weekly, ref 0xgovernor:id), or a curator’s name with a URL |
curated |
true once staff have edited the event by hand; an importer refreshes uncurated fields only |
Exported as the events dataset, through the app rather than the warehouse:
the columns are ChainEvent::CSV_HEADERS, hashes complete and pipe-joined.
Refresh: the hacks import weekly (Mondays 06:00 UTC), the depeg detector
daily (06:00 UTC, from the hourly bars), governance events weekly (Mondays
07:00 UTC); a curated event changes when staff change it.
Dataset runs: dataset_runs
One row per scheduled pass over a dataset, read by the admin ClickHouse page
so the newest row per dataset says when a table was last extended and
whether it worked. Postgres, so it renders during a warehouse outage.
| Column | Meaning |
|---|---|
dataset_key |
aave_v3_liquidations, spark_liquidations, morpho_liquidations, compound_v3_absorbs, aave_reference_data, timeline_anchors |
status |
running, succeeded, failed or skipped (the warehouse lease was held, the table is missing, or the sandbox left the work to production: nothing went wrong, nothing was done) |
from_block / to_block |
the range this run covered; to_block < from_block means the table was already at the head |
rows_written |
rows the extractor wrote, updated chunk by chunk so a run killed mid-way still says how far it got |
error |
the exception, or the reason for a skip |
Coverage statements: protocol_coverages
One row per run of the job that produced a tracking dataset (a panel
cross-section, a nightly extraction), written by that job from what it just
wrote. The tracking pages, the CSV header comments and the guides read the
newest row per (protocol, dataset); nothing recounts the warehouse to state
coverage.
| Column | Meaning |
|---|---|
protocol |
the tracking slug: aave, spark, makerdao, compound-v3, morpho |
dataset |
health (the Aave-style panel), vaults (Maker’s panel), liquidations, absorptions |
unit |
what is counted: accounts, vaults, liquidations, absorptions |
block / cadence / day |
the cross-section the statement describes, for a panel run; null for an extraction, which describes the whole table |
total / computed |
units the run saw, and units it computed a number for |
skipped |
{ reason => count } in the pipeline’s own vocabulary (emode, gho_debt, unsupported_price, not_a_balance, debt:no_price, decimals_unknown, unvalued); the pages label them (unsupported_price reads adapter oracle) |
computed_at |
when the run finished |
The sentence the pages print is "#{computed} of #{total} #{unit} computed;
skipped: …", and the same sentence opens every tracking CSV as a # comment
line, followed by a # run: line naming the time and the block.
Maker ilk registry: maker_ilks
Maker’s on-chain IlkRegistry, persisted: one row per ilk the registry has ever
listed since the first sync. Read by the collateral composition (which ilks
and which adapters), the vault panel (which classes hold a balance) and the
Maker page. Refreshed by the nightly reference-data job and by
rake maker:ilks:sync; rake maker:validate:ilks syncs and then fails on
drift between the chain and the fallback constants.
| Column | Meaning |
|---|---|
ilk |
the collateral type, e.g. ETH-A; unique |
name / symbol / decimals / gem |
the collateral token as the registry describes it |
klass |
the registry’s class (1 standard, 2 legacy, 3 RWA, 4 D3M, 5 allocator, 6 Lite PSM, 7 staking engine); see Maker |
join_adapter |
the adapter the composition reads flows from; null for a class that holds none |
pip |
the price feed, for reference |
registered |
false once the registry stops listing the ilk: it is kept with its last-known facts and reported as retired |
synced_block / synced_at |
the head block the registry was read at, and when |
Protocol coverage registry: protocol_candidates
One row per (protocol, chain), because coverage is a grid and not a list:
Aave on Ethereum and Aave on BSC are different deployments, and “what becomes
real when we ingest BSC” has to include the second one.
| Column | Meaning |
|---|---|
slug / chain |
unique together; the slug is DeFiLlama’s, so re-import is idempotent |
category |
Lending and CDP are the roadmap; other categories are recorded so the registry can say what is not covered, without implying it is planned |
model |
pool, cdp, comet or isolated — the four shapes the platform can already replicate. Null means unclassified, never guessed: a wrong model makes an expensive protocol look cheap |
tvl_usd |
that chain’s share, not the protocol total repeated on every chain |
tracked_as |
the TrackedProtocol slug when this is already covered — how Sky reconciles to makerdao |
source / fetched_at |
which source gave these facts and when. No chain assignment rests on memory |
Populated by bin/rails protocols:discover. It is deliberately not
TrackedProtocol: that is the seven live entries, edited by deploy, driving a
public roadmap that must not drift from what is built. This is a research list
of hundreds whose TVL changes weekly and which nobody has promised.
Morpho Blue liquidations: dfrds_morpho_liquidations
One row per Liquidate event. Every amount is in that market’s own tokens:
there is no USD column and no cross-market total, because each market names
its own oracle. See Morpho Blue.
| Column | Meaning |
|---|---|
block / block_timestamp |
the block of the Liquidate event and its timestamp, UTC |
tx_hash / log_index |
the transaction, complete, and the log’s position in the block |
liquidator / borrower |
who repaid and who was liquidated |
market_id |
the market’s id; loan_token/collateral_token are its ERC-20s, loan_symbol/collateral_symbol their symbols on record |
lltv |
liquidation LTV, 1e18 = 100% |
repaid_raw / seized_raw / bad_debt_raw |
unscaled, in the token’s own decimals |
repaid / seized / bad_debt |
scaled: 0 when the token’s decimals are unknown, never guessed |
bad_debt |
the shortfall written off against this market’s suppliers, in the loan token |
bad_debt_raw > 0 is the filter for “this liquidation cost the suppliers
money”. Shares (repaidShares, badDebtShares) are decoded but not stored:
they are internal accounting, not amounts.
Refresh: nightly at 03:55 UTC, resuming from the newest stored block and
stopping 64 blocks behind the head.
Second factor: on users
| Column | Meaning |
|---|---|
otp_secret |
the TOTP seed, encrypted at rest; null when 2FA is off |
pending_otp_secret |
a replacement authenticator’s seed while the live one still works, encrypted at rest; promoted to otp_secret only when a code from it verifies, and null otherwise |
otp_required_for_login |
whether sign-in asks for a code: set only after a code has verified |
consumed_timestep |
the last accepted 30-second window, so a code can’t be replayed |
otp_backup_codes |
bcrypt digests of the recovery codes, never the codes |
otp_enabled_at |
when it was switched on |
A recovery code is removed from the array as it is consumed, so
otp_backup_codes.size is how many remain. See two-factor
authentication.
Research pages: over the API
| Field | Meaning |
|---|---|
tags |
kind:name labels, shared within the page’s space |
blocks[].kind |
text, heading, code, callout, divider |
blocks[].settings |
kind-specific: heading level, code language, callout tone |
citations[].verification_state |
verified, mismatch, unresolved, unverified |
public_url |
present only when the page is published; null otherwise, never a broken link |
A mismatch means the value no longer matches what the chain says. Treat it as
a finding, not a formatting detail.
Bundle sales: bundle_sales
What a partner sold, and the split it produced. Every column is a snapshot
taken at the moment of sale and is never recomputed, so repricing a bundle or
renegotiating a cap cannot move a historical record.
| Column | Meaning |
|---|---|
bundle_name |
the bundle’s name at sale time, not today’s |
seats |
seats sold; may be fewer than the bundle’s own count, priced pro rata |
list_price_cents |
the bundle’s full price when it was sold |
charged_cents |
what the institution was actually charged |
per_seat_cents |
the implied rate, which a later top-up is priced against |
discount_percent |
the partner’s margin. Never exposed to the institution |
partner_share_cents |
what the partner earned. Never exposed to the institution |
dfrds_share_cents |
what dfrds recognised. partner_share + dfrds_share == charged |
sold_at |
when the sale was recorded |
recognized_at |
when payment arrived. Null means earned-but-unpaid; earnings count recognised sales only |
stripe_invoice_id |
the invoice the payment reconciles to, when there is one |
Bundle authorisations: partner_bundles
Which bundles a partner may sell, and their cap on each.
| Column | Meaning |
|---|---|
max_discount_percent |
the cap on this bundle |
| — | the effective cap is the lower of this and partners.max_discount_percent, so raising one alone can never widen what a partner may do |
Plans: plans
| Column | Meaning |
|---|---|
price_cents |
the price per billing period; for a per-seat plan, the price of one seat. Null means undecided: the row is listed, not sold, until staff set it |
per_seat |
sold with a quantity; the organization’s allowance follows the subscription item’s quantity |
seat_minimum |
the smallest quantity checkout accepts on a per-seat plan |
seat_limit |
the allowance of a fixed plan, and the fallback for a per-seat plan with no quantity recorded |
stripe_lookup_key |
how the Stripe price is found; dfrds_data_monthly and dfrds_data_annual are live and fixed |
organizations.purchased_seats is the capacity bought (per-seat quantity, or
bundle seats plus top-ups) and purchased_seat_cents the rate it was bought
at; both are null for an organization that bought none.
Payment state: on organizations
| Column | Meaning |
|---|---|
payment_state |
ok, past_due (a renewal failed, inside the 14-day grace period) or grace_expired (the grace ran out: data downloads and the API are closed until a payment lands) |
payment_failed_at |
when the first failed invoice of the episode arrived; the grace period is 14 days from here, and a retry does not move it |
payment_failed_invoice_url |
Stripe’s hosted invoice, so every notice can link it |
payment_failed_amount_cents |
what was due |
Driven by invoice.payment_failed and invoice.paid; the notices are
billing_events rows of type local.dunning, one per step and episode.
Plan limits: mcp_calls_per_day
MCP tool calls allowed per API key per day, counted apart from
api_requests_per_hour.
| Default | 2000 (Plan::DEFAULT_LIMITS) |
| Window | Calendar day, UTC; resets at midnight |
| Scope | Per API key, not per organization |
| Refusal | HTTP 429, X-RateLimit-Limit / X-RateLimit-Remaining |
Deliberately generous: an agent answering one research question may make a
dozen tool calls, so a limit set by REST intuition would be far too tight. The
number should be revisited once there is a week of real usage behind it.
api_keys.mcp_call_count and api_keys.mcp_last_used_at are lifetime
counters on the key, shown on the organization page. They are counters rather
than a per-period record because MCP is not a billing dimension today; making
it one would need retained per-period rows instead.
Alerts: alerts
Non-price alerts. price_alerts remains a separate table for price
thresholds, which predate this one and were deliberately not migrated.
| Column | Meaning |
|---|---|
kind |
liquidation or chain_event |
condition |
jsonb, per kind. Liquidation: token, optional protocols[]. Event: optional category, chain, protocol — all absent means every event |
space_id |
Alerts belong to a space; firing emails every member of it |
status |
active or triggered. One-shot: it will not fire again until re-armed |
triggered_payload |
jsonb snapshot of what actually matched, kept so the email and the record agree |
Firing is idempotent: Alert#fire! returns false on an already-triggered
alert. This matters because the liquidation extractor and the event importer
both re-run over overlapping ranges by design, so “nothing fires twice” has to
be a property of the model rather than of every caller.
Derived citations: derived_citations
An aggregate over a bounded query, cited like a value.
| Column | Meaning |
|---|---|
dataset / filters |
The query, in the export path’s own vocabulary — the same fields a DataRequest holds, read by the same DatasetCatalogue and DatasetQuery |
aggregate / column |
count, sum, avg, min or max; the column is intersected with the dataset’s own variables |
display_value |
The answer as it was when cited. Text, so a re-derivation compares like with like rather than through float coercion |
content_hash |
SHA-256 of the canonical spec plus the result. Resolves publicly at /citations/:hash |
verification_state |
unverified, verified, mismatch, unresolved — the same four value_citations uses |
verification_note |
On a mismatch, what it re-derived as. The cited value is never rewritten: both figures are kept, because a number that moved is itself a finding |
The spec is canonicalised with sorted filter keys, so the same query hashes
the same way however the filters arrived — and citing the same claim twice
returns the same citation rather than a duplicate.
Dataset citations: dataset_citations
The hash of the canonical bytes of one dataset query, resolving publicly at
/citations/:hash (HTML, .json DataCite, .bib, .cff, and .csv for
subscribers while the bytes still match).
| Column | Meaning |
|---|---|
kind |
price_series (one pool’s canonical series; params holds pool, pair, protocol, chain, period, from, to) or dataset (any catalogue query) |
spec |
For dataset: dataset (a catalogue key), filters (as DataRequestFilters writes them, keys sorted, blanks dropped), columns (in the catalogue’s order) and block_range ([from, to], the blocks the bytes covered, pinned at creation and applied on re-derivation) |
content_hash |
SHA-256 of the canonical CSV: catalogue column order, natural-key row order, one number spelling, empty nulls, LF, UTF-8 |
row_count / as_of |
The rows the bytes hold and the last date they reach |
named_organization_id |
The citing user’s organization when they chose to be named as a creator; nullified if the organization goes |
verification_state |
unverified, verified, mismatch, unresolved: the same four value_citations uses, set by the nightly re-derivation |
verification_note |
On a mismatch, the digest the spec produces now. The cited hash is never rewritten |
The version a citation reports is the dataset_releases row it falls in
(block containment, or the last date for datasets without blocks), or
unreleased. A price_series citation is matched against the price_bars
releases.
Dataset releases: dataset_releases
One row per dataset per month, cut by BuildDatasetReleasesJob on the first
at 06:00 UTC under the warehouse lease. Refresh: monthly. The raw log table
has no releases.
| Column | Meaning |
|---|---|
dataset_key |
A catalogue key |
version |
YYYY.MM, unique per dataset |
block_from / block_to |
The table’s block extent at release, for datasets with a block column |
as_of |
The last value of the date column at release, for the rest |
row_count |
Rows in the release |
content_hash |
SHA-256 of the full canonical export (every column, natural-key order), streamed through the digest; the same bytes CanonicalDataset writes for the whole dataset over that block range |
released_at |
When it was cut |
Contract ABIs: contract_abis
The explorer’s ABI cache, one row per (chain, address). See
decoded events for how rows get here.
| Column | Meaning |
|---|---|
address / chain |
lowercase hex, no 0x; ethereum |
abi |
jsonb, the ABI as fetched (the implementation’s for a proxy). Registry rows hold events only |
source |
static (the built-in registry), sourcify, or etherscan |
verified |
the ABI came from a verified source; false on a miss |
implementation_address |
set when the address is an EIP-1967 proxy: the ABI describes this contract |
fetched_at |
when the ABI was written |
searched_at / found |
the search log, as in contract_labels and event_signatures: a hit is never looked up again, a miss is retried after seven days |
Warehouse gaps: warehouse_gaps
What the daily completeness check (CheckWarehouseCompletenessJob, 00:30
UTC, over the previous UTC day) found short in the bulk table. Listed on
the status page while open. A row is a finding, never a repair.
| Column | Meaning |
|---|---|
chain |
eth_mainnet |
block_from / block_to |
the range, inclusive: a 1,000-block window clipped to the day (source head) or a single sampled block (source rpc) |
expected |
blocks with at least one log in the range according to the source |
found |
the same count from eth_logs_wide |
source |
head: compared against the follower’s head table where it overlapped the day; rpc: a sampled block the node’s receipts say emitted logs, absent from the bulk table |
detected_at |
the last run that found it short; a range seen again is refreshed, not duplicated |
resolved_at |
set by the first later run over that day that finds the range complete |
Export checksums: data_requests.checksum_sha256
The SHA-256 of the delivered gzip file, taken after it was written (the
warehouse’s file is streamed back through the digest; a registry export is
hashed as it is built). Shown on the download page, sent as
X-Checksum-SHA256 with the download, carried in the export’s citation
line and in the data_export.ready webhook and data.exported audit row.