Skip to content

fix(rpc): align eth_feeHistory response with execution-apis spec#963

Open
songgaoye wants to merge 3 commits into
developfrom
song/fix_eth_feeHistory
Open

fix(rpc): align eth_feeHistory response with execution-apis spec#963
songgaoye wants to merge 3 commits into
developfrom
song/fix_eth_feeHistory

Conversation

@songgaoye
Copy link
Copy Markdown

Closes: #XXX

Description


For contributor use:

  • Targeted PR against correct branch (see CONTRIBUTING.md)
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the module structure standards.
  • Wrote unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Added relevant godoc comments.
  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer

For admin use:

  • Added appropriate labels to PR (ex. WIP, R4R, docs, etc)
  • Reviewers assigned
  • Squashed all commits, uses message "Merge pull request #XYZ: [title]" (coding standards)

@songgaoye songgaoye requested a review from a team as a code owner May 25, 2026 10:48
@songgaoye songgaoye requested review from calvinaco and randy-cro and removed request for a team May 25, 2026 10:48
@github-actions

This comment has been minimized.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 44.20%. Comparing base (f959eb9) to head (ae4b09d).
⚠️ Report is 4 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop     #963      +/-   ##
===========================================
+ Coverage    44.15%   44.20%   +0.04%     
===========================================
  Files          196      196              
  Lines        16896    16910      +14     
===========================================
+ Hits          7461     7475      +14     
  Misses        8645     8645              
  Partials       790      790              
Files with missing lines Coverage Δ
rpc/backend/chain_info.go 78.01% <100.00%> (+1.73%) ⬆️
rpc/types/types.go 7.89% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@songgaoye
Copy link
Copy Markdown
Author

@claude

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 25, 2026

Claude finished @songgaoye's task in 5m 10s —— View job


PR Review: fix(rpc): align eth_feeHistory response with execution-apis spec

  • Gather context and read changed files
  • Analyze code changes
  • Post comprehensive review

Summary

This PR makes two changes to eth_feeHistory:

  1. Silently cap blockCount when it exceeds FeeHistoryCap, instead of returning an error.
  2. Add baseFeePerBlobGas and blobGasUsedRatio fields (EIP-4844 blob fields) to the response, populated with zeros since Ethermint doesn't support blob transactions.

Both changes improve alignment with the execution-apis spec.


Issues Found

Behavioral Change: Silent Cap Instead of Error

rpc/backend/chain_info.go:216–218

The previous behavior returned an error when blocks > maxBlockCount. The new behavior silently caps. This is spec-compliant (go-ethereum caps at 1024 without erroring), but it is a breaking change for clients that relied on the error response to detect invalid or over-limit requests.

The PR description should clearly document this behavioral change. Consider adding a note in the changelog that this is a breaking client-facing behavior change.

Edge Case: FeeHistoryCap = 0 Produces a Nonsensical Response

The test at rpc/backend/chain_info_test.go:350 shows that when FeeHistoryCap = 0 and userBlockCount = 1:

  • blocks gets capped to 0
  • oldestBlock becomes blockNumber + 1 = 2, a block that doesn't exist yet
  • The response returns an empty history with a future oldestBlock

This is a confusing but pre-existing invariant exposed by the silent-cap change. With the old error-returning behavior, FeeHistoryCap = 0 would immediately return an error for any non-zero blockCount. With silent capping, callers silently receive a degenerate response. If FeeHistoryCap = 0 is a valid configuration to mean "no fee history", a zero guard could help:

if blocks == 0 {
    return &rpctypes.FeeHistoryResult{
        OldestBlock: (*hexutil.Big)(big.NewInt(0)),
        BaseFee:     []*hexutil.Big{},
        GasUsedRatio: []float64{},
    }, nil
}

Fix this →

Minor: Inconsistent omitempty Usage

rpc/types/types.go:179,181

GasUsedRatio has no omitempty (always serialized), while BlobGasUsedRatio has omitempty. Since the code always initializes BlobGasUsedRatio with a non-nil slice (make([]float64, blocks)), the omitempty tag on BlobGasUsedRatio has no effect in practice (Go's encoding/json only omits slices when they are nil, not when they are empty). This is a documentation/intention mismatch — if the intent is to allow omitting the field for pre-Cancun nodes in the future, a comment explaining this would help; otherwise, removing omitempty for consistency would be cleaner.

Blob Fields Always Return Zeros

thisBlobBaseFee and thisBlobGasUsedRatio are always initialized with zero values. Since Ethermint doesn't implement EIP-4844, this is correct for now. However, there is no comment explaining why, which could confuse future contributors. A short comment such as // EIP-4844 blob transactions are not supported; return zeros per spec would be helpful.


Positive Aspects

  • Spec compliance: JSON field names baseFeePerBlobGas and blobGasUsedRatio exactly match the execution-apis spec.
  • Silent cap aligns with go-ethereum's behavior.
  • Test coverage is updated for all changed cases; Codecov confirms 100% coverage of modified lines.
  • CHANGELOG entry is present.

Verdict

The changes are correct and improve spec compliance. The main concerns are:

  1. The silent-cap behavioral change should be explicitly noted (it's a client-facing API behavior change).
  2. The FeeHistoryCap = 0 edge case produces a counterintuitive response with a future oldestBlock.

These are not blocking issues for the change's intent, but worth addressing before merge.
| Branch: song/fix_eth_feeHistory

Comment thread rpc/backend/chain_info.go
Comment thread rpc/backend/chain_info.go
Comment thread rpc/types/types.go Outdated
@songgaoye
Copy link
Copy Markdown
Author

@claude

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 25, 2026

Claude finished @songgaoye's task in 1m 52s —— View job


PR Review: fix(rpc): align eth_feeHistory response with execution-apis spec

  • Gather context and read changed files
  • Analyze code changes
  • Post comprehensive review

Summary

This PR makes two improvements to eth_feeHistory:

  1. Silent cap: When blockCount exceeds FeeHistoryCap, the value is silently capped instead of returning an error — matching go-ethereum's behavior.
  2. EIP-4844 blob fields: baseFeePerBlobGas and blobGasUsedRatio fields are added to the response (always zeroed since Ethermint doesn't support blob transactions).

No consensus/state changes — this is a pure RPC-layer change and is safe to merge to release branches.


Issues Found

Behavioral Change: Silent Cap Instead of Error

rpc/backend/chain_info.go:216–218

The previous behavior returned an error when blocks > maxBlockCount. The new behavior silently caps. This aligns with go-ethereum's behavior but is a breaking change for any client that relied on the error response to detect over-limit requests. The PR description and changelog entry should explicitly document this behavioral change.

Minor: Inconsistent omitempty Between Blob Fields

rpc/types/types.go:180–181

BlobBaseFee      []*hexutil.Big   `json:"baseFeePerBlobGas,omitempty"`
BlobGasUsedRatio []float64        `json:"blobGasUsedRatio"`

BlobBaseFee has omitempty while BlobGasUsedRatio does not. In Go's encoding/json, omitempty only omits a slice when it is nil — an initialized empty slice ([]*hexutil.Big{}) is always serialized. Since BlobBaseFee is always initialized in this code (either []*hexutil.Big{} in the zero-block path or a fully populated slice), the omitempty tag never triggers in practice. This is not a bug, but it creates an inconsistency between the two new fields. Consider either removing omitempty from BlobBaseFee for consistency, or matching the pattern of BaseFee (which has omitempty) and documenting the intent.


Positive Aspects

  • Zero-block guard (rpc/backend/chain_info.go:219–227): The if blocks == 0 guard correctly handles both userBlockCount = 0 and the FeeHistoryCap = 0 case, returning a clean empty response rather than the previous behavior that would compute a future oldestBlock.
  • Correct array lengths: thisBlobBaseFee uses blocks+1 (matching baseFeePerGas per spec) and thisBlobGasUsedRatio uses blocks (matching gasUsedRatio). Both are correct per the execution-apis spec.
  • Comment added at line 329 explaining why blob fields are hardcoded to zero — clear and helpful for future contributors.
  • JSON field names baseFeePerBlobGas and blobGasUsedRatio match the execution-apis spec exactly.
  • Test coverage: All changed cases are covered and Codecov reports 100% coverage of modified lines.
  • CHANGELOG entry is present.

Verdict

The changes are correct, well-tested, and improve spec compliance. The two points above are minor: the behavioral change documentation is a PR description concern, and the omitempty inconsistency has no runtime impact. Neither is blocking.
| Branch: song/fix_eth_feeHistory

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.

2 participants