Skip to content

fix: use empty access list if eth_createAccessList returns error#1799

Merged
georgehao merged 4 commits intodevelopfrom
fix/commit_tx_error
Mar 9, 2026
Merged

fix: use empty access list if eth_createAccessList returns error#1799
georgehao merged 4 commits intodevelopfrom
fix/commit_tx_error

Conversation

@georgehao
Copy link
Member

@georgehao georgehao commented Mar 9, 2026

Purpose or design rationale of this PR

Symptom:

error="missing required field 'storageKeys' for AccessTuple

Root cause: ethereum/go-ethereum#33656 adds slices.SortedFunc inside access list tracer, which returns nil if the input slice is empty.

Technically it's a bug in upstream geth, but we make our code more robust and defensive.

PR title

Your PR title must follow conventional commits (as we are doing squash merge for each PR), so it must start with one of the following types:

  • fix: A bug fix

Deployment tag versioning

Has tag in common/version.go been updated or have you added bump-version label to this PR?

  • No, this PR doesn't involve a new deployment, git tag, docker image tag
  • Yes

Breaking change label

Does this PR have the breaking-change label?

  • No, this PR is not a breaking change
  • Yes

Summary by CodeRabbit

  • Bug Fixes
    • Gas estimation now ignores access-list creation errors and continues gracefully, reducing failed estimations.
  • Chores
    • Version bumped to v4.7.13.

@georgehao georgehao requested a review from Thegaram March 9, 2026 11:48
@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

Bumped package version to v4.7.13 and changed gas estimation to ignore eth_createAccessList errors (returning the gas limit without an access list), removing the errors import; no other behavioral changes introduced.

Changes

Cohort / File(s) Summary
Version Bump
common/version/version.go
Updated package-level tag from v4.7.12 to v4.7.13.
Gas estimation / access-list handling
rollup/internal/controller/sender/estimategas.go
In estimateGasLimit, treat eth_createAccessList RPC errors and returned error strings as non-fatal by returning the gas limit without an access list and a nil error; removed unused errors import. No other control-flow changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

bump-version

Suggested reviewers

  • jonastheis
  • colinlyguo

Poem

🐰 I hopped the tag to v4.7.13,
I nudged away a noisy error scene,
Gas stays counted, lists set free,
A quiet hop — that's good for me.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description explains the symptom and root cause but lacks clarity on the solution approach and implementation details despite the template asking 'What does this PR do? Why does it do it? How does it do it?' Expand the description to explicitly explain what the code changes do, why this defensive approach is chosen, and how the new error-handling logic works.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly describes the main change: using an empty access list when eth_createAccessList returns an error, which aligns with the primary modification in estimategas.go.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/commit_tx_error

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 and usage tips.

Thegaram
Thegaram previously approved these changes Mar 9, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
rollup/internal/controller/sender/estimategas.go (1)

156-183: Consider adding a unit test for the nil StorageKeys scenario.

While the fix is correct, it would be valuable to add a test case that verifies finetuneAccessList handles entries with nil StorageKeys correctly, ensuring the returned access list always has non-nil slices.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rollup/internal/controller/sender/estimategas.go` around lines 156 - 183, Add
a unit test for finetuneAccessList that constructs an input types.AccessList
containing an entry whose StorageKeys is nil (and at least one entry matching
the 'to' address and one not), call finetuneAccessList with a known
gasLimitWithAccessList and to address, then assert the returned access list
pointer is non-nil, every returned types.AccessTuple.StorageKeys is a non-nil
slice (length may be zero), entries matching the removed-to logic are omitted
from the new list and the gasLimitWithAccessList value is adjusted according to
the removal rules; use the finetuneAccessList function and
types.AccessList/types.AccessTuple types in the test to locate code under test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@rollup/internal/controller/sender/estimategas.go`:
- Around line 156-183: Add a unit test for finetuneAccessList that constructs an
input types.AccessList containing an entry whose StorageKeys is nil (and at
least one entry matching the 'to' address and one not), call finetuneAccessList
with a known gasLimitWithAccessList and to address, then assert the returned
access list pointer is non-nil, every returned types.AccessTuple.StorageKeys is
a non-nil slice (length may be zero), entries matching the removed-to logic are
omitted from the new list and the gasLimitWithAccessList value is adjusted
according to the removal rules; use the finetuneAccessList function and
types.AccessList/types.AccessTuple types in the test to locate code under test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 38a638bb-0d5c-4259-832c-02b23452f72d

📥 Commits

Reviewing files that changed from the base of the PR and between 9b2b5e0 and e579aa2.

📒 Files selected for processing (2)
  • common/version/version.go
  • rollup/internal/controller/sender/estimategas.go

@codecov-commenter
Copy link

codecov-commenter commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 36.41%. Comparing base (9b2b5e0) to head (9e02a48).
⚠️ Report is 1 commits behind head on develop.

Files with missing lines Patch % Lines
rollup/internal/controller/sender/estimategas.go 0.00% 6 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1799      +/-   ##
===========================================
- Coverage    36.41%   36.41%   -0.01%     
===========================================
  Files          248      248              
  Lines        21321    21325       +4     
===========================================
  Hits          7765     7765              
- Misses       12733    12737       +4     
  Partials       823      823              
Flag Coverage Δ
rollup 35.12% <0.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
rollup/internal/controller/sender/estimategas.go (1)

133-140: Add regression coverage for the new fallback contract.

These branches now silently degrade to EstimateGas instead of failing the send path. Please add focused tests for both rpcErr and non-empty errStr so this behavior change stays intentional and doesn’t regress unnoticed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rollup/internal/controller/sender/estimategas.go` around lines 133 - 140, Add
regression tests that assert the send flow falls back to EstimateGas when
CreateAccessList returns an RPC error or a non-empty errStr: mock
s.gethClient.CreateAccessList to first return a non-nil rpcErr and verify the
code path returns gasLimitWithoutAccessList and triggers the EstimateGas
fallback, then a separate test where CreateAccessList returns rpcErr nil but
errStr non-empty and assert the same fallback behavior; target the function that
calls s.gethClient.CreateAccessList (the estimator in estimategas.go) and ensure
both branches (rpcErr and non-empty errStr) are covered so future changes to
CreateAccessList handling are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@rollup/internal/controller/sender/estimategas.go`:
- Around line 133-140: Add regression tests that assert the send flow falls back
to EstimateGas when CreateAccessList returns an RPC error or a non-empty errStr:
mock s.gethClient.CreateAccessList to first return a non-nil rpcErr and verify
the code path returns gasLimitWithoutAccessList and triggers the EstimateGas
fallback, then a separate test where CreateAccessList returns rpcErr nil but
errStr non-empty and assert the same fallback behavior; target the function that
calls s.gethClient.CreateAccessList (the estimator in estimategas.go) and ensure
both branches (rpcErr and non-empty errStr) are covered so future changes to
CreateAccessList handling are caught.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ece63717-b7b8-4e5f-8829-e3d3f4e0baf1

📥 Commits

Reviewing files that changed from the base of the PR and between e579aa2 and 4c0b0dc.

📒 Files selected for processing (1)
  • rollup/internal/controller/sender/estimategas.go

Thegaram
Thegaram previously approved these changes Mar 9, 2026
@Thegaram Thegaram changed the title fix commit tx missing StorageKeys fix: use empty access list if eth_createAccessList returns error Mar 9, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
rollup/internal/controller/sender/estimategas.go (1)

164-185: ⚠️ Potential issue | 🟠 Major

Initialize the rebuilt access list as empty, not nil.

The code normalizes StorageKeys at the tuple level, but if every entry is filtered out, newAccessList remains nil. Since Go's encoding/json marshals nil slices as null and non-nil empty slices as [], and types.AccessList has no custom marshaling, the caller can still receive null instead of [] on the downstream signer/RPC path, which may cause compatibility issues.

Initialize with a pre-allocated capacity instead:

Suggested fix
-	var newAccessList types.AccessList
+	newAccessList := make(types.AccessList, 0, len(*accessList))
 	for _, entry := range *accessList {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rollup/internal/controller/sender/estimategas.go` around lines 164 - 185,
newAccessList is currently declared nil so if every access-list entry is
filtered it will marshal as JSON null; change its initialization to a non-nil
empty slice (e.g., create newAccessList with make(types.AccessList, 0,
len(*accessList)) or make(types.AccessList, 0)) before the loop to ensure it
serializes as [] and keep the rest of the loop logic (the StorageKeys
normalization and the return of &newAccessList) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@rollup/internal/controller/sender/estimategas.go`:
- Around line 133-145: Add unit tests that exercise the new fallback semantics
in estimateGasLimit and ensure getFeeData propagation remains correct: mock/stub
s.gethClient.CreateAccessList to return (1) a non-nil rpcErr, (2) a non-empty
errStr, and (3) a successful accessList with gasLimitWithAccessList; call
estimateGasLimit (or the higher-level getFeeData flow that invokes
estimateGasLimit) and assert that in cases (1) and (2) the function returns
gasLimitWithoutAccessList and no error (i.e., the code falls back to sending
without an access list), and in case (3) it returns the gasLimitWithAccessList
and the access list; ensure tests reference estimateGasLimit,
s.gethClient.CreateAccessList and getFeeData/sender submission path to validate
end-to-end behavior.

---

Outside diff comments:
In `@rollup/internal/controller/sender/estimategas.go`:
- Around line 164-185: newAccessList is currently declared nil so if every
access-list entry is filtered it will marshal as JSON null; change its
initialization to a non-nil empty slice (e.g., create newAccessList with
make(types.AccessList, 0, len(*accessList)) or make(types.AccessList, 0)) before
the loop to ensure it serializes as [] and keep the rest of the loop logic (the
StorageKeys normalization and the return of &newAccessList) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 458faee6-0c81-49eb-aa37-ccfad99a350b

📥 Commits

Reviewing files that changed from the base of the PR and between 4c0b0dc and cfb0e13.

📒 Files selected for processing (1)
  • rollup/internal/controller/sender/estimategas.go

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
rollup/internal/controller/sender/estimategas.go (1)

133-145: ⚠️ Potential issue | 🟠 Major

Add regression coverage for the fallback path before merging.

These branches now silently downgrade CreateAccessList failures to “send without access list”, but this file still has 0% patch coverage. Please cover the rpcErr, errStr, and success paths through estimateGasLimit or the higher-level fee-data flow so this behavior change stays pinned down.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rollup/internal/controller/sender/estimategas.go` around lines 133 - 145, Add
unit/integration tests exercising the CreateAccessList fallback by driving
s.gethClient.CreateAccessList to return (1) a non-nil rpcErr, (2) a non-empty
errStr, and (3) a successful accessList+gasLimitWithAccessList result, then
assert estimateGasLimit (or the higher-level fee-data flow that calls
estimateGasLimit) returns the gasLimitWithoutAccessList and no access list for
cases (1) and (2) and the access-list gas for case (3). Mock or stub the
gethClient used by sender to control CreateAccessList responses, and cover the
rpcErr, errStr, and success branches so the fallback behavior is exercised.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@rollup/internal/controller/sender/estimategas.go`:
- Around line 133-145: Add unit/integration tests exercising the
CreateAccessList fallback by driving s.gethClient.CreateAccessList to return (1)
a non-nil rpcErr, (2) a non-empty errStr, and (3) a successful
accessList+gasLimitWithAccessList result, then assert estimateGasLimit (or the
higher-level fee-data flow that calls estimateGasLimit) returns the
gasLimitWithoutAccessList and no access list for cases (1) and (2) and the
access-list gas for case (3). Mock or stub the gethClient used by sender to
control CreateAccessList responses, and cover the rpcErr, errStr, and success
branches so the fallback behavior is exercised.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 33cebab8-b00e-458d-8630-539aef2bd9f7

📥 Commits

Reviewing files that changed from the base of the PR and between cfb0e13 and 9e02a48.

📒 Files selected for processing (1)
  • rollup/internal/controller/sender/estimategas.go

@georgehao georgehao merged commit 167f26e into develop Mar 9, 2026
6 checks passed
@georgehao georgehao deleted the fix/commit_tx_error branch March 9, 2026 14:01
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.

3 participants