Skip to content

fix(evm): replace sunset blocknative gas oracle with eth_feeHistory - #1281

Merged
kaladinlight merged 2 commits into
developfrom
fix/evm-gas-fees-feehistory
Jun 23, 2026
Merged

fix(evm): replace sunset blocknative gas oracle with eth_feeHistory#1281
kaladinlight merged 2 commits into
developfrom
fix/evm-gas-fees-feehistory

Conversation

@kaladinlight

@kaladinlight kaladinlight commented Jun 23, 2026

Copy link
Copy Markdown
Member

Problem

Blocknative's gas platform was sunset on 2026-06-19, so GET /gas/fees now returns a 404 on every EVM coinstack. MoralisService.getGasFees() was querying api.blocknative.com/gasprices/blockprices:

ApiError: Request failed with status code 404
    at MoralisService.getGasFees (.../evm/moralisService.js)

Fix

Replace Blocknative with eth_feeHistory-based estimation off the PublicClient the service already holds — no third-party gas vendor, no new credentials:

  • base fee: next-block value from feeHistory (protocol-deterministic, exact)
  • priority fees: reward percentiles [50, 70, 90]slow / average / fast
  • outlier filter: drop tips above median × 10 so MEV/overpayer txs don't skew the average (ported from the old GasOracle.getFeeThreshold; adaptive — clips relative to current conditions)
  • 100-block sample window, baseFee × 2 maxFeePerGas buffer, existing minPriorityFee floor preserved

Output shape (GasFees) is unchanged, so the OP-stack L1-fee wrappers (OptimismGasFees / BaseGasFees) and all downstream consumers are untouched.

Percentile tuning

[50, 70, 90] was chosen empirically against live RPCs:

  • p50 slow (not p1) keeps the low tier robust against under-quoting / stuck txs.
  • p90 fast (not p95) avoids chasing Ethereum's persistent MEV-tip tail, which made fast ~2× more expensive than needed on an idle chain.

Cleanup

  • Removed the now-unused BLOCKNATIVE_API_KEY env var across all coinstacks.
  • Deleted the dead BlockbookService and GasOracle — no coinstack has instantiated them since the Moralis cutover (2025-11); they survived only as a type union + an instanceof branch in the EVM controller.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Chores
    • Removed Blocknative API key requirement from EVM blockchain node configurations across all supported chains (Arbitrum, Avalanche, Base, BSC, Ethereum, Gnosis, Optimism, Polygon).
    • Updated API key requirements: Arbitrum now uses ALCHEMY_API_KEY; Gnosis now uses ETHERSCAN_API_KEY.
    • Streamlined blockchain node service architecture for transaction history and gas fee estimation.

Blocknative's gas platform was sunset on 2026-06-19, so /gas/fees now
404s on every EVM coinstack (MoralisService.getGasFees queried
api.blocknative.com/gasprices/blockprices).

Replace it with eth_feeHistory-based estimation off the existing
PublicClient (no third-party gas vendor):
- next-block base fee from feeHistory (protocol-deterministic)
- priority fees from reward percentiles [50, 70, 90] -> slow/average/fast
- clip tips above median * 10 to drop mev/overpayer outliers
- 100-block sample window, baseFee * 2 maxFee buffer, minPriorityFee floor

Remove the now-unused BLOCKNATIVE_API_KEY env var across coinstacks, and
delete the dead BlockbookService and GasOracle (no coinstack has
instantiated them since the Moralis cutover in 2025-11).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kaladinlight
kaladinlight requested a review from a team as a code owner June 23, 2026 15:15
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kaladinlight, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 43 minutes and 2 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 65b38273-013c-4976-a0ad-1235de73266a

📥 Commits

Reviewing files that changed from the base of the PR and between 34aa892 and 17db438.

📒 Files selected for processing (1)
  • node/coinstacks/common/api/src/evm/moralisService.ts
📝 Walkthrough

Walkthrough

Removes BlockbookService and GasOracle modules entirely from the EVM common API. Replaces Blocknative gas price API calls in MoralisService.getGasFees() with eth_feeHistory-based percentile estimation. Narrows EVM.service to MoralisService only and simplifies gnosis chain tx history branching. Removes BLOCKNATIVE_API_KEY from all chain sample.env files.

Changes

Blocknative and BlockbookService removal

Layer / File(s) Summary
Type and barrel export cleanup
node/coinstacks/common/api/src/evm/types.ts, node/coinstacks/common/api/src/evm/index.ts
BlockNativeResponse and DebugCallStack interfaces removed from exported types; ./gasOracle and ./blockbookService re-exports removed from the module barrel.
MoralisService eth_feeHistory gas estimation
node/coinstacks/common/api/src/evm/moralisService.ts
Blocknative imports and env var validation removed from MoralisService; fee-history constants added (FEE_HISTORY_BLOCK_COUNT, reward percentiles, BASE_FEE_MULTIPLIER, OUTLIER_THRESHOLD_MULTIPLIER); getGasFees() rewritten to call client.getFeeHistory(), derive per-percentile priority fees, clip outliers via median threshold, and return slow/average/fast fee bundles.
EVM controller narrowed to MoralisService
node/coinstacks/common/api/src/evm/controller.ts
BlockbookService import removed; EVM.service static type changed from BlockbookService | MoralisService to MoralisService; gnosis chain getTxHistory path simplified to unconditionally call getTxHistoryWithEtherscanInternalTxs.
sample.env BLOCKNATIVE_API_KEY removal
node/coinstacks/arbitrum/sample.env, node/coinstacks/avalanche/sample.env, node/coinstacks/base/sample.env, node/coinstacks/bnbsmartchain/sample.env, node/coinstacks/ethereum/sample.env, node/coinstacks/gnosis/sample.env, node/coinstacks/optimism/sample.env, node/coinstacks/polygon/sample.env
BLOCKNATIVE_API_KEY removed from all chain sample env templates; arbitrum substitutes ALCHEMY_API_KEY; gnosis substitutes ETHERSCAN_API_KEY.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hop, hop, away goes Blocknative's key,
No more oracles needed, we're finally free!
eth_feeHistory blooms where old APIs sat,
Percentiles and medians — imagine that!
The blockbook is shelved, the union type gone,
One service, one path — the rabbit hops on! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: replacing Blocknative's sunset gas oracle with eth_feeHistory-based fee estimation in the EVM service.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/evm-gas-fees-feehistory

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
node/coinstacks/common/api/src/evm/moralisService.ts (1)

386-395: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Tiers may not be monotonic across slow/average/fast.

Each tier's priority fee is averaged with an independent median-based outlier clip, so in skewed samples it's possible for a lower percentile tier to produce a higher estimate than a higher one (e.g. slow > average). Consider clamping so slow ≤ average ≤ fast to avoid surfacing inverted fee tiers to clients.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@node/coinstacks/common/api/src/evm/moralisService.ts` around lines 386 - 395,
The fee tier calculations in the REWARD_PERCENTILES.map block calculate slow,
average, and fast tiers independently, which can result in non-monotonic fee
values where slower tiers have higher fees than faster ones. After the array
destructuring of [slow, average, fast], add clamping logic to ensure monotonic
ordering by enforcing that slow's fees are clamped to be at most average's fees,
and average's fees are clamped to be at most fast's fees. This should be applied
to the gasPrice, maxFeePerGas, and maxPriorityFeePerGas values in each tier
object.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@node/coinstacks/common/api/src/evm/moralisService.ts`:
- Around line 386-395: The fee tier calculations in the REWARD_PERCENTILES.map
block calculate slow, average, and fast tiers independently, which can result in
non-monotonic fee values where slower tiers have higher fees than faster ones.
After the array destructuring of [slow, average, fast], add clamping logic to
ensure monotonic ordering by enforcing that slow's fees are clamped to be at
most average's fees, and average's fees are clamped to be at most fast's fees.
This should be applied to the gasPrice, maxFeePerGas, and maxPriorityFeePerGas
values in each tier object.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 61e29b74-c934-4b11-ae64-84b95352ad34

📥 Commits

Reviewing files that changed from the base of the PR and between 99d5dd4 and 34aa892.

📒 Files selected for processing (14)
  • node/coinstacks/arbitrum/sample.env
  • node/coinstacks/avalanche/sample.env
  • node/coinstacks/base/sample.env
  • node/coinstacks/bnbsmartchain/sample.env
  • node/coinstacks/common/api/src/evm/blockbookService.ts
  • node/coinstacks/common/api/src/evm/controller.ts
  • node/coinstacks/common/api/src/evm/gasOracle.ts
  • node/coinstacks/common/api/src/evm/index.ts
  • node/coinstacks/common/api/src/evm/moralisService.ts
  • node/coinstacks/common/api/src/evm/types.ts
  • node/coinstacks/ethereum/sample.env
  • node/coinstacks/gnosis/sample.env
  • node/coinstacks/optimism/sample.env
  • node/coinstacks/polygon/sample.env
💤 Files with no reviewable changes (12)
  • node/coinstacks/ethereum/sample.env
  • node/coinstacks/polygon/sample.env
  • node/coinstacks/optimism/sample.env
  • node/coinstacks/base/sample.env
  • node/coinstacks/gnosis/sample.env
  • node/coinstacks/arbitrum/sample.env
  • node/coinstacks/common/api/src/evm/blockbookService.ts
  • node/coinstacks/common/api/src/evm/index.ts
  • node/coinstacks/bnbsmartchain/sample.env
  • node/coinstacks/common/api/src/evm/gasOracle.ts
  • node/coinstacks/common/api/src/evm/types.ts
  • node/coinstacks/avalanche/sample.env

Each tier's priority fee is averaged with an independent median-based
outlier clip, so on skewed samples a lower percentile tier could exceed
a higher one (e.g. slow > fast). Use a running max to enforce
slow <= average <= fast while also applying the minPriorityFee floor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kaladinlight
kaladinlight merged commit f5c7f66 into develop Jun 23, 2026
3 checks passed
@kaladinlight
kaladinlight deleted the fix/evm-gas-fees-feehistory branch June 23, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant