Skip to content

Conversation

@d4mr
Copy link
Contributor

@d4mr d4mr commented Aug 22, 2025

  • Updated the error handling logic to include a new function is_unsupported_eip1559_error, which checks for unsupported feature errors and specific error messages related to method availability.
  • Modified the transaction processing logic to utilize this new error handling function, improving the robustness of the EoaExecutorWorker's response to unsupported EIP-1559 features.

Summary by CodeRabbit

  • New Features

    • None
  • Bug Fixes

    • Improved handling when connected nodes do not support EIP-1559, reducing transaction failures by reliably falling back to legacy gas pricing.
    • More robust detection of RPC errors related to unsupported features, leading to smoother transaction submission.
  • Refactor

    • Internal API and export organization adjusted with no user-visible behavior changes.
    • Reduced logging verbosity by recording transaction counts instead of full payloads.

…errors

- Updated the error handling logic to include a new function `is_unsupported_eip1559_error`, which checks for unsupported feature errors and specific error messages related to method availability.
- Modified the transaction processing logic to utilize this new error handling function, improving the robustness of the EoaExecutorWorker's response to unsupported EIP-1559 features.
@coderabbitai
Copy link

coderabbitai bot commented Aug 22, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Adds a helper to detect unsupported EIP‑1559 RPC errors, updates the transaction worker to use it when deciding to fall back to legacy gas pricing, repositions a public re-export for EoaTransactionRequest, and reduces tracing output by logging transaction slice length instead of full slice.

Changes

Cohort / File(s) Summary
Error handling utility
executors/src/eoa/worker/error.rs
Added pub fn is_unsupported_eip1559_error(error: &RpcError<TransportErrorKind>) -> bool which returns true for RpcError::UnsupportedFeature or for RpcError::ErrorResp messages containing "method not found".
Transaction worker & public exports
executors/src/eoa/worker/transaction.rs
Replaced direct pattern match for unsupported EIP‑1559 with call to is_unsupported_eip1559_error(&eip1559_error); re-export position of EoaTransactionRequest moved within the crate's public exports.
Store tracing change
executors/src/eoa/store/atomic.rs
Changed tracing to log transactions_length = transactions.len() instead of logging full transactions slice content in atomic_move_pending_to_borrowed_with_incremented_nonces.

Sequence Diagram(s)

sequenceDiagram
  participant TW as TransactionWorker
  participant RPC as Node RPC

  TW->>RPC: Submit EIP‑1559 transaction
  RPC-->>TW: Success or Error

  alt Error
    TW->>TW: call is_unsupported_eip1559_error(error)
    alt Unsupported EIP‑1559
      note right of TW #DDDDFF: Fallback path (legacy gas)
      TW->>RPC: Submit legacy (pre‑1559) transaction
      RPC-->>TW: Result
    else Other error
      TW-->>TW: Propagate error
    end
  else Success
    TW-->>TW: Continue normal flow
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5def3de and ef8afe9.

📒 Files selected for processing (1)
  • executors/src/eoa/store/atomic.rs (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch pb/extend-unsupported-rpc-feature-detection

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 0

Caution

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

⚠️ Outside diff range comments (1)
executors/src/eoa/worker/transaction.rs (1)

199-219: Fallback to legacy on EIP-1559 unsupported: ensure fee fields are mutually exclusive

Switching to the helper is a solid maintainability win. One correctness concern: if the incoming request had one EIP-1559 fee set (e.g., user provided max_fee_per_gas but not max_priority), and 1559 estimation fails, we set gas_price but leave any previously set 1559 fields intact. Depending on Alloy’s TypedTransaction inference, this can lead to ambiguous or unintended type selection.

Mitigate by clearing 1559 fields when falling back to legacy, or reconstructing a legacy-only request prior to setting gas_price. Also consider making the EIP-7702 error message explicit that the failure derives from 1559 fee estimation being unsupported.

Suggested change (adjust field accessors if direct fields aren’t public; alternatively, rebuild the request):

-                            Ok(gas_price) => {
-                                tracing::debug!("Using legacy gas price: {}", gas_price);
-                                Ok(tx.with_gas_price(gas_price))
-                            }
+                            Ok(gas_price) => {
+                                tracing::debug!("Using legacy gas price: {}", gas_price);
+                                // Ensure we don't carry partial 1559 fields into a legacy tx
+                                let mut tx_legacy = tx;
+                                // If these fields are not publicly settable, rebuild the request instead.
+                                tx_legacy.max_fee_per_gas = None;
+                                tx_legacy.max_priority_fee_per_gas = None;
+                                Ok(tx_legacy.with_gas_price(gas_price))
+                            }

Optionally refine the EIP-7702 message:

-                        Err(EoaExecutorWorkerError::TransactionBuildFailed {
-                            message: "EIP7702 transactions not supported on chain".to_string(),
-                        })
+                        Err(EoaExecutorWorkerError::TransactionBuildFailed {
+                            message: "EIP-7702 requires EIP-1559 fee support, which is not available on this chain/provider"
+                                .to_string(),
+                        })

If helpful, I can provide a quick helper like fn clear_eip1559_fees(tx: AlloyTransactionRequest) -> AlloyTransactionRequest to encapsulate this.

🧹 Nitpick comments (5)
executors/src/eoa/worker/error.rs (3)

241-242: "invalid opcode" classified as non-retryable — consider expanding deterministic EVM error patterns

Good call marking "invalid opcode" as deterministic/non-retryable. To reduce noisy retries further, consider also capturing other well-known deterministic EVM execution errors often surfaced in RPC messages (client-dependent phrasing), e.g., "invalid op", "bad instruction", "invalid jump". This keeps the retry loop focused on genuine transients.

Apply this diff to extend the filter:

-            // if the error message contains "invalid chain", it's not retryable
-            !(message.contains("invalid chain") || message.contains("invalid opcode"))
+            // if the error message indicates an invalid chain or deterministic EVM fault, it's not retryable
+            !(message.contains("invalid chain")
+                || message.contains("invalid opcode")
+                || message.contains("invalid op")
+                || message.contains("bad instruction")
+                || message.contains("invalid jump"))

327-338: Broaden EIP-1559 unsupported detection beyond just “method not found”

Relying solely on "method not found" risks false negatives. Clients/providers vary: common variants include "method is not available", "the method does not exist", "unknown/unsupported method", or explicit "EIP-1559 not supported"/"London not activated". Also, many return JSON-RPC code -32601. Consider matching a small set of phrases and, if accessible, the error code.

Additionally, prefer to_ascii_lowercase over to_lowercase to avoid locale pitfalls.

Proposed improvement:

 pub fn is_unsupported_eip1559_error(error: &RpcError<TransportErrorKind>) -> bool {
     if let RpcError::UnsupportedFeature(_) = error {
         return true;
     }

     if let RpcError::ErrorResp(resp) = error {
-        let message = resp.message.to_lowercase();
-        return message.contains("method not found");
+        let message = resp.message.to_ascii_lowercase();
+        // Common JSON-RPC phrasings from various clients/providers
+        let method_unavailable = [
+            "method not found",
+            "method is not available",
+            "the method does not exist",
+            "unknown method",
+            "unsupported method",
+        ]
+        .iter()
+        .any(|p| message.contains(p));
+
+        let eip1559_unavailable = message.contains("eip-1559")
+            && (message.contains("not supported")
+                || message.contains("unsupported")
+                || message.contains("not available"));
+
+        let fee_methods_unavailable = (message.contains("eth_feehistory")
+            || message.contains("eth_maxpriorityfeepergas"))
+            && (message.contains("not found")
+                || message.contains("not available")
+                || message.contains("does not exist")
+                || message.contains("unsupported"));
+
+        // If resp.code is available, consider also: resp.code == -32601
+        return method_unavailable || eip1559_unavailable || fee_methods_unavailable;
     }

     false
 }

If you’d like, I can add a small unit-test module covering:

  • UnsupportedFeature arm
  • ErrorResp with "method is not available"
  • ErrorResp with "unknown method"
  • ErrorResp with explicit "EIP-1559 not supported"
  • A negative case (unrelated RPC error)

154-205: Nit: share phrase lists between classifiers to keep semantics consistent

You now have several places matching error phrases (classify_send_error, is_retryable_rpc_error, and is_unsupported_eip1559_error). Consider centralizing phrase lists and helpers to avoid drift.

executors/src/eoa/worker/transaction.rs (2)

176-196: Trace more context when 1559 estimation succeeds

Minor improvement: include chain_id and provider URL (if available) in the success log to simplify multi-chain debugging.


160-175: Pre-check could short-circuit 1559 path for known non-1559 chains

If Chain exposes London/EIP-1559 activation metadata, you can short-circuit to legacy for those chains, skipping the RPC round-trip. Not blocking; the current approach safely handles unknowns.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9cab16d and 5def3de.

📒 Files selected for processing (2)
  • executors/src/eoa/worker/error.rs (2 hunks)
  • executors/src/eoa/worker/transaction.rs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
executors/src/eoa/worker/error.rs (1)
executors/src/eoa/error_classifier.rs (1)
  • message (224-236)
executors/src/eoa/worker/transaction.rs (1)
executors/src/eoa/worker/error.rs (2)
  • is_retryable_preparation_error (247-278)
  • is_unsupported_eip1559_error (327-338)
🔇 Additional comments (5)
executors/src/eoa/worker/transaction.rs (5)

25-27: Import updates — looks good

Bringing is_unsupported_eip1559_error into this scope keeps the estimation path readable and avoids duplicating pattern logic.


304-354: Gas estimation revert handling — solid coverage

The revert/oversized branches are thorough and correctly scoped to TransactionSimulationFailed vs RPCError. No action needed.


30-55: Backoff arithmetic — safe and readable

The retry loop with exponential backoff is reasonable for preparation errors. No action needed.


171-175: Guardrails align with fee-estimation contracts

Skipping EIP-1559 estimation when gas_price is present and returning early when both 1559 fees are present is correct and avoids unnecessary RPCs.


197-205: The script will dump lines 150–220 of transaction.rs so we can see the full context around the EIP-1559 fallback branch.

…action length instead of transactions directly.
@d4mr d4mr merged commit 1d4e650 into main Aug 22, 2025
2 of 3 checks passed
@d4mr d4mr deleted the pb/extend-unsupported-rpc-feature-detection branch August 22, 2025 19:10
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