iotexproject / iotexproject/iotex-core
web3: support `finalized`/`safe` block tags in eth_getBlockByNumber (+ minor EVM-RPC compat gaps)
- Dominant language
- Go
- Stars
- 1.6k
- Forks
- 382
- Avg merge
- 4d 22h
- Merged PRs (30d)
- 17
Description
## Summary
IoTeX's EVM JSON-RPC (`api/web3server.go`) does not recognize the standard `finalized` / `safe` block tags, plus a few smaller EVM-compatibility gaps in the same area. The primary ask is `finalized`/`safe`; the rest are bundled because they live in the same handler.
Tested against the public endpoint `https://babel-api.mainnet.iotex.io` (node `v2.4.4`).
## 1. `finalized` / `safe` block tags (primary)
`eth_getBlockByNumber` with `finalized` or `safe` fails today:
```
$ curl -s $RPC -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["finalized",false]}'
{"code":-32603,"message":"strconv.ParseUint: parsing \"finalized\": invalid syntax"}
$ curl -s $RPC -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["safe",false]}'
{"code":-32603,"message":"strconv.ParseUint: parsing \"safe\": invalid syntax"}
```
`parseBlockNumber` only recognizes the three tags defined at `api/web3server.go:93-95` (`pending` / `latest` / `earliest`); any other string falls through to `strconv.ParseUint` and errors.
These tags are standard on Ethereum (since The Merge, 2022), BSC (BEP-126 fast finality), and Polygon PoS (Heimdall v2 milestones). IoTeX is the outlier among modern EVM chains in not exposing them — even though it is the easiest case: Roll-DPoS gives instant/deterministic finality, so both `safe` and `finalized` can map directly to the latest committed (irreversible) block.
Motivation: cross-chain bridges, indexers, and wallets increasingly gate on the `finalized` tag for reorg-safe confirmation logic. Against IoTeX today those tools get a hard error and must special-case the chain.
**Proposed fix:** recognize `safe` and `finalized` in `parseBlockNumber` (next to the constants at `api/web3server.go:93-95`) and resolve both to the current tip / last irreversible block.
## 2. `eth_feeHistory` parses `blockCount` as decimal (bug)
```
$ curl -s $RPC -d '{"jsonrpc":"2.0","id":1,"method":"eth_feeHistory","params":["0x5","latest",[25,50,75]]}'
{"code":-32603,"message":"strconv.ParseUint: parsing \"0x5\": invalid syntax"}
```
`feeHistory` parses the `blockCount` param with base-10 `strconv.ParseUint` (`api/web3server.go:352`), but the JSON-RPC spec sends it as a hex quantity (`0x5`). Standard callers (e.g. MetaMask EIP-1559 fee estimation) therefore fail. It should be parsed as a hex quantity.
## 3. Missing methods (optional parity)
- `eth_getProof` (EIP-1186) — returns `web3 method not found`. Used by light clients and state-proof consumers.
- `eth_createAccessList` (EIP-2930) — returns `web3 method not found`.
- `txpool_*` namespace — absent.
## Priority
(1) is the concrete request. (2) is a small bug fix. (3) are optional parity items.
cc @envestcc
Contributor guide
Research direction
Start in api/web3server.go, especially parseBlockNumber around lines 93-95 and feeHistory around line 352. Check the existing handler behavior against the supplied eth_getBlockByNumber and eth_feeHistory requests. Done means safe and finalized resolve to the intended committed tip and hexadecimal blockCount requests are accepted; the optional missing methods remain separately scoped.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, blockchain
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 56/100