matter-labs / matter-labs/block-explorer
Base token is never added to the tokens DB on ZKsync OS chains
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 139
- Forks
- 145
- Avg merge
- 8h 3m
- Merged PRs (30d)
- 3
Description
### Bug Report
#### Description
On ZKsync OS chains the base token never appears in the tokens DB, so it is missing from the token list and can never receive off-chain data (price, icon).
Root cause: the worker only creates the base token row when a contract exists at `0x800a`. On ZKsync OS there is no ERC-20-style contract there. The VM handles the base token as native account state and a system hook intercepts all calls to `0x800a`, reverting on everything except the withdraw selectors, so `name()/symbol()/decimals()` always revert.
- `addBaseToken()` (`packages/worker/src/token/token.service.ts:189`) requires an existing address row for `0x800a` to satisfy the Token entity's non-null `blockNumber`/`transactionHash`/`logIndex` (FKs to blocks/transactions), so it silently skips. The TODO on line 190 already notes this.
- The fallback path in `transaction.processor.ts:125` only fires when the data-fetcher emits a token with `l2Address == 0x800a`, which never happens without a deployment event.
This affects every ZKsync OS chain regardless of what `BASE_TOKEN_*` env vars are set to, since the config values are only written through the `0x800a` code paths.
Note: base token identity is available on-chain if wanted. On protocol v31 the L2 NativeTokenVault (`0x10004`) exposes `BASE_TOKEN_NAME()/BASE_TOKEN_SYMBOL()/BASE_TOKEN_DECIMALS()/BASE_TOKEN_ORIGIN_TOKEN()`. On v30.x, `NTV.WETH_TOKEN()` returns the wrapped base token, whose `l1Address()` getter holds the base token's L1 address.
#### Reproduction Steps
1. Run the explorer against any ZKsync OS chain with `BASE_TOKEN_*` env vars configured.
2. Query `/tokens` on the API.
#### Expected Behavior
The base token is listed with the configured (or on-chain) metadata and can be matched by the off-chain data updater.
#### Current Behavior
The base token row is never created. `addBaseToken()` is a silent no-op.
#### Possible Solution
Allow the base token row to exist without deployment provenance (e.g. nullable `blockNumber`/`transactionHash`/`logIndex` or a synthetic genesis anchor) and populate it from config and/or the NTV getters. Overlaps with the direction proposed in #455, related symptom in #403.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with addBaseToken() in packages/worker/src/token/token.service.ts and the fallback in packages/worker/src/transaction/transaction.processor.ts. Inspect the Token entity constraints and the direction in #455, then compare the v31 NativeTokenVault getters with the v30.x WETH_TOKEN path. Done means the configured or on-chain base token appears in /tokens and can receive off-chain metadata.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend, blockchain, database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100