Skip to main content

Question it answers

“Give me the ERC-20 metadata (name / symbol / decimals / total_supply) for token 0x….” Mirrors Moralis GET /erc20/metadata.
The recipe lands one observation per TOKEN-type deployed contract and projects it into a one-row-per-token metadata surface. Token metadata is fixed at deploy time, so there is normally exactly one row per (chain_id, token_address); the latest deploy by (block_number, transaction_index) is canonical (defensive against a CREATE2 re-deploy at a reused address).

What you get

One row per token contract, keyed by token_address: Token contracts are filtered to real ERC-20 deploys: a contract is kept only if its symbol is non-empty and ≤ 100 chars, decimals ≤ 50, and deployer_address is non-empty.

Source

The transform reads the per-block deployedContracts array, filtered to entries whose type contains TOKEN (the token-contract slice of the block EVM data). Each surviving entry becomes one row. deployedContracts carries no log index, so transaction_index is the intra-block tiebreaker: one deploy per (tx, contract).

Destination

ClickHouse uses the collapsing log-table pattern (see the recipes overview) so chain reorganizations self-correct. The fact table’s sort key is token-first, so a token’s metadata is a point lookup. Postgres derives the current-metadata surface as a DISTINCT ON (token_address) materialized view; MySQL maintains it incrementally via an AFTER INSERT latest-wins trigger.

Full schema

The complete read table this recipe produces. Keep the columns you need and drop the rest (see Schema & flexibility). total_supply is the raw uint256 stored as text / wide integer (it exceeds standard numeric precision); apply decimals at read time for the human-readable value.
The sign column drives reorg collapsing: read with FINAL or a sign-aware aggregate, and take the latest deploy with argMax(…, (block_number, transaction_index)). A single-node setup can use CollapsingMergeTree(sign) without the replication path. Because metadata is fixed at deploy, there is normally one row per token; the latest-deploy logic only matters for a CREATE2 re-deploy at a reused address.
Refresh the view on a schedule: REFRESH MATERIALIZED VIEW CONCURRENTLY token_metadata;. total_supply is NUMERIC(76, 0): the explicit precision keeps large raw supplies from overflowing. MySQL is the same shape with DECIMAL(65,0) for total_supply and VARCHAR(255) for name / symbol, maintaining token_metadata incrementally via an AFTER INSERT latest-wins trigger. position is the block-level cursor used during backfill.

Example reads

Metadata for one token, latest deploy wins (ClickHouse):
All tokens deployed in a block range (ClickHouse):
Current metadata for one token (Postgres, after refreshing the view):

Modes

Shipped defaults: ClickHouse hybrid (backfill → realtime), Postgres / MySQL historical (one-shot backfill). For live/reorg-safe ingestion, use ClickHouse; see the overview.
The Postgres / MySQL realtime reorg path needs a single-column UNIQUE on the position column, but position is block-level (one block can deploy several token contracts), so array-expanded rows can only carry a composite unique. Run realtime/hybrid on ClickHouse, where the collapsing log table corrects reorgs per-block. The Postgres / MySQL configs are intended for historical backfill; a once-off metadata census is the dominant use of this recipe anyway.

Multichain

The recipe is chain-parametrized via the chain setting: point it at any supported EVM chain. The vendor_event_id already includes chain_id, tx_hash, transaction_index, and token_address, so rows stay unique without the Solana log-index widening other recipes need. Note that SPL token metadata does not flow through deployedContracts the way EVM contract deploys do; this recipe is EVM-shaped.

Fidelity gaps

The core on-chain fields (token_address, name, symbol, decimals, total_supply, plus block_number and deployer_address) are fully sourced. A few enrichment fields GET /erc20/metadata returns are not sourced here, as they come from off-chain or separate pipelines:
  • logo / thumbnail / logo_hash: off-chain logo CDN assets.
  • validated / possible_spam / verified_contract: Moralis spam & verification heuristics.
  • categories: editorial token categorisation.
  • created_at (wall-clock): this recipe carries on-chain block_number / block_timestamp instead.
Also note total_supply is the raw uint256 with no decimals applied; divide by 10^decimals for the human-readable supply.

Migrating from the REST API

GET /erc20/metadata: ERC-20 token metadata

This recipe replaces the endpoint’s on-chain core: name, symbol, decimals, total_supply, and the deploy position come through exactly, with no batch cap on how many contracts you look up per query.
Not 1:1. fully_diluted_valuation needs a price join: pair this recipe with Token Prices and multiply. The endpoint’s editorial layer (logo / thumbnail, possible_spam / verified_contract / validated / security_score, categories, links, description) is off-chain: bring your own token list and allow/deny lists, or drop those fields. market_cap needs an off-chain circulating_supply (there is no on-chain equivalent); FDV is the on-chain-derivable alternative.
Any set of contracts in one query, with formatted supply and FDV (Postgres):
  • Backfill from the deploy block. Metadata is captured at contract deployment, so a token only appears if its deploy block is indexed; for arbitrary token lookups, run historical / hybrid over full history.
  • total_supply is raw and live: no decimals applied (scale at read time), and it tracks mint/burn, so keep the feed current for an up-to-date figure.
  • created_at isn’t on the token_metadata view; read block_timestamp from token_metadata_observations (Postgres) or event_ts on the ClickHouse fact table.
  • The recipe is EVM-shaped: SPL token metadata doesn’t flow through deployedContracts (see Multichain).

Token Holders

All non-zero holders of a token; pair with metadata for decimals and symbol.

Token Analytics

The use case this metadata census powers: the decimals lookup behind every scaled amount.