Skip to content

refactor: simplify logic across crates#56

Merged
chengwenxi merged 3 commits intomainfrom
refactor/simplify-crates
Mar 25, 2026
Merged

refactor: simplify logic across crates#56
chengwenxi merged 3 commits intomainfrom
refactor/simplify-crates

Conversation

@panos-xyz
Copy link
Copy Markdown
Contributor

@panos-xyz panos-xyz commented Mar 23, 2026

Summary

  • simplify repeated validation and builder logic across consensus, engine-api, payload, primitives, revm, rpc, and txpool paths
  • fold several local morph transaction handling paths down to smaller same-file helpers in txpool, evm, and node
  • keep the work on a single branch with the two requested commits together

Test Plan

  • cargo test -p morph-txpool -p morph-evm -p morph-node --lib
  • cargo check --workspace

Summary by CodeRabbit

  • Refactor

    • Consolidated error handling with type conversion implementations for improved consistency.
    • Extracted helper methods to reduce code duplication across payload and block tag management.
    • Simplified receipt field construction and RLP encoding logic through shared utility functions.
    • Removed redundant constructor methods in favor of default implementations.
  • Chores

    • Removed unused code patterns and import statements to improve codebase cleanliness.

Eliminate duplication and reduce boilerplate:

- consensus: Add From<MorphConsensusError> for ConsensusError, simplify 12 error sites
- primitives/receipt: Extract rlp_header_inner_impl, use as_receipt() delegation
- primitives/transaction: Use matches! macro, simplify encode_2718, extract decode_common_fields
- revm/token_fee: Reuse compute_mapping_slot_for_address, merge query_erc20_balance
- revm/tx: Chain builder calls
- revm/handler: Simplify reimburse_caller paths
- engine-api: Extract update_block_tag helper
- payload: Remove redundant new() wrappers, simplify builder constructors
- chainspec: Remove duplicate comment
- rpc: Remove duplicate import alias

Net reduction: ~70 lines, no functional changes.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 23, 2026

📝 Walkthrough

Walkthrough

This PR consolidates and refactors code across multiple crates by extracting helper methods, delegating to existing utilities, removing redundant constructors, and simplifying error handling through trait conversions. Changes maintain existing functionality while improving code maintainability and reducing duplication.

Changes

Cohort / File(s) Summary
Error Handling & Conversion
crates/consensus/src/error.rs, crates/consensus/src/validation.rs
Added From<MorphConsensusError> conversion impl and updated error handling sites to use .into() for cleaner error propagation.
Helper Method Extraction
crates/engine-api/src/builder.rs, crates/node/src/node.rs, crates/txpool/src/validator.rs
Extracted shared logic into private helper methods: update_block_tag for tag updates, payload_builder_config for config construction, and insufficient_funds_outcome for validation errors.
Closure & Field Consolidation
crates/evm/src/block/mod.rs, crates/revm/src/tx.rs
Introduced local closures and consolidated builder chains to centralize field/struct construction in receipt and transaction environments.
Constructor Cleanup
crates/payload/builder/src/builder.rs, crates/payload/types/src/executable_l2_data.rs, crates/payload/types/src/safe_l2_data.rs
Removed redundant new() constructors and delegated MorphPayloadBuilder::new to with_config, while removing const qualifier from with_config.
Receipt & Transaction Encoding Refactoring
crates/primitives/src/receipt/envelope.rs, crates/primitives/src/receipt/mod.rs, crates/primitives/src/transaction/envelope.rs, crates/primitives/src/transaction/l1_transaction.rs
Refactored to delegate to existing RLP/type helpers, extract shared header logic, and use direct pattern matching instead of duplicating match blocks.
Fee & Token Balance Handling
crates/revm/src/handler.rs, crates/revm/src/token_fee.rs
Adjusted MorphTx fee reimbursement to fall through for ETH fees, consolidated balance query logic, and removed duplicate function wrappers.
Minor Cleanup
crates/chainspec/src/spec.rs, crates/revm/src/precompiles.rs, crates/rpc/src/types/transaction.rs
Removed duplicate comment header, unused imports, and updated trait method delegation paths.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • anylots
  • chengwenxi

Poem

🐰 A rabbit hops through code so grand,
Extracting helpers, hand in hand,
No .to_string() chains to see,
Just .into() flowing free,
Less duplication, clean and neat—refactoring's quite a treat!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: simplify logic across crates' is fully related to the changeset, which involves numerous refactoring improvements across multiple crates including consensus, engine-api, payload, primitives, revm, rpc, and txpool.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/simplify-crates

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.

Copy link
Copy Markdown

@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.

Caution

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

⚠️ Outside diff range comments (1)
crates/revm/src/token_fee.rs (1)

258-268: ⚠️ Potential issue | 🟠 Major

Don't squash EVMError::Database into a zero balance here.

This helper now returns Ok(U256::ZERO) for every system_call_one failure, which makes the Err(EVMError::Database(_)) arm in read_token_balance_with_fallback dead. A backend read failure then gets misreported as a zero token balance / insufficient-funds condition instead of surfacing the real DB error.

Suggested fix
     match evm.system_call_one(token, calldata) {
         Ok(result) if result.is_success() => {
             if let Some(output) = result.output()
                 && output.len() >= 32
             {
                 return Ok(U256::from_be_slice(&output[..32]));
             }
             Ok(U256::ZERO)
         }
         Ok(_) => Ok(U256::ZERO),
-        Err(_) => Ok(U256::ZERO),
+        Err(err @ EVMError::Database(_)) => Err(err),
+        Err(_) => Ok(U256::ZERO),
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/revm/src/token_fee.rs` around lines 258 - 268, The current match on
evm.system_call_one(token, calldata) maps all failures to Ok(U256::ZERO), which
hides EVMError::Database and makes read_token_balance_with_fallback's
database-error arm unreachable; update the Err(_) arm to inspect the error
(capture it as Err(e)) and if it is EVMError::Database return Err(e) (propagate
the DB error) otherwise keep returning Ok(U256::ZERO); locate the match around
evm.system_call_one in token_fee.rs and change the Err arm accordingly so
EVMError::Database is not squashed.
🧹 Nitpick comments (1)
crates/primitives/src/transaction/morph_transaction.rs (1)

400-432: LGTM! Clean DRY refactor.

The helper successfully eliminates duplication by extracting the 11 common RLP fields shared by both V0 and V1 decoders. The decoding order matches the encoding order in encode_fields, and error propagation is correct.

💡 Optional: Consider a helper struct for better readability

The 11-element tuple is a bit unwieldy. If this grows further, consider a private helper struct with named fields:

+#[derive(Debug)]
+struct CommonFields {
+    chain_id: ChainId,
+    nonce: u64,
+    max_priority_fee_per_gas: u128,
+    max_fee_per_gas: u128,
+    gas_limit: u64,
+    to: TxKind,
+    value: U256,
+    input: Bytes,
+    access_list: AccessList,
+    fee_token_id: u16,
+    fee_limit: U256,
+}
+
-fn decode_common_fields(buf: &mut &[u8]) -> alloy_rlp::Result<(...)> {
+fn decode_common_fields(buf: &mut &[u8]) -> alloy_rlp::Result<CommonFields> {
-    Ok((
-        Decodable::decode(buf)?,
-        ...
-    ))
+    Ok(CommonFields {
+        chain_id: Decodable::decode(buf)?,
+        ...
+    })

However, for a stable 11-field set, the current tuple approach is fine.

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

In `@crates/primitives/src/transaction/morph_transaction.rs` around lines 400 -
432, The current decode_common_fields returns an 11-element tuple which is hard
to read; create a private helper struct (e.g., CommonTxFields) with named fields
for chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to,
value, input, access_list, fee_token_id, fee_limit, change decode_common_fields
to return that struct instead of a tuple, and update any callers (V0/V1 decoders
that unpack decode_common_fields) and the encode_fields implementation to
construct/consume CommonTxFields; keep the decoding logic identical but use
named fields for clarity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@crates/revm/src/token_fee.rs`:
- Around line 258-268: The current match on evm.system_call_one(token, calldata)
maps all failures to Ok(U256::ZERO), which hides EVMError::Database and makes
read_token_balance_with_fallback's database-error arm unreachable; update the
Err(_) arm to inspect the error (capture it as Err(e)) and if it is
EVMError::Database return Err(e) (propagate the DB error) otherwise keep
returning Ok(U256::ZERO); locate the match around evm.system_call_one in
token_fee.rs and change the Err arm accordingly so EVMError::Database is not
squashed.

---

Nitpick comments:
In `@crates/primitives/src/transaction/morph_transaction.rs`:
- Around line 400-432: The current decode_common_fields returns an 11-element
tuple which is hard to read; create a private helper struct (e.g.,
CommonTxFields) with named fields for chain_id, nonce, max_priority_fee_per_gas,
max_fee_per_gas, gas_limit, to, value, input, access_list, fee_token_id,
fee_limit, change decode_common_fields to return that struct instead of a tuple,
and update any callers (V0/V1 decoders that unpack decode_common_fields) and the
encode_fields implementation to construct/consume CommonTxFields; keep the
decoding logic identical but use named fields for clarity.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a0fdec55-f943-461b-857f-eb147553f91d

📥 Commits

Reviewing files that changed from the base of the PR and between 0f3f0a7 and 5accf48.

📒 Files selected for processing (20)
  • crates/chainspec/src/spec.rs
  • crates/consensus/src/error.rs
  • crates/consensus/src/validation.rs
  • crates/engine-api/src/builder.rs
  • crates/evm/src/block/mod.rs
  • crates/node/src/node.rs
  • crates/payload/builder/src/builder.rs
  • crates/payload/types/src/executable_l2_data.rs
  • crates/payload/types/src/safe_l2_data.rs
  • crates/primitives/src/receipt/envelope.rs
  • crates/primitives/src/receipt/mod.rs
  • crates/primitives/src/transaction/envelope.rs
  • crates/primitives/src/transaction/l1_transaction.rs
  • crates/primitives/src/transaction/morph_transaction.rs
  • crates/revm/src/handler.rs
  • crates/revm/src/precompiles.rs
  • crates/revm/src/token_fee.rs
  • crates/revm/src/tx.rs
  • crates/rpc/src/types/transaction.rs
  • crates/txpool/src/validator.rs
💤 Files with no reviewable changes (4)
  • crates/chainspec/src/spec.rs
  • crates/revm/src/precompiles.rs
  • crates/payload/types/src/executable_l2_data.rs
  • crates/payload/types/src/safe_l2_data.rs

Copy link
Copy Markdown

@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)
crates/primitives/src/receipt/mod.rs (1)

131-167: Consider applying the same as_receipt() simplification for consistency.

Since rlp_encoded_fields_length and rlp_encode_fields now delegate to as_receipt(), you could apply the same pattern here for consistency:

♻️ Optional refactor to use `as_receipt()` for consistency
     pub fn rlp_encoded_fields_length_without_bloom(&self) -> usize {
-        match self {
-            Self::Legacy(r)
-            | Self::Eip2930(r)
-            | Self::Eip1559(r)
-            | Self::Eip7702(r)
-            | Self::Morph(r) => {
-                r.inner.status.length()
-                    + r.inner.cumulative_gas_used.length()
-                    + r.inner.logs.length()
-            }
-            Self::L1Msg(r) => r.status.length() + r.cumulative_gas_used.length() + r.logs.length(),
-        }
+        let r = self.as_receipt();
+        r.status.length() + r.cumulative_gas_used.length() + r.logs.length()
     }

     pub fn rlp_encode_fields_without_bloom(&self, out: &mut dyn BufMut) {
-        match self {
-            Self::Legacy(r)
-            | Self::Eip2930(r)
-            | Self::Eip1559(r)
-            | Self::Eip7702(r)
-            | Self::Morph(r) => {
-                r.inner.status.encode(out);
-                r.inner.cumulative_gas_used.encode(out);
-                r.inner.logs.encode(out);
-            }
-            Self::L1Msg(r) => {
-                r.status.encode(out);
-                r.cumulative_gas_used.encode(out);
-                r.logs.encode(out);
-            }
-        }
+        let r = self.as_receipt();
+        r.status.encode(out);
+        r.cumulative_gas_used.encode(out);
+        r.logs.encode(out);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/primitives/src/receipt/mod.rs` around lines 131 - 167, The two methods
rlp_encoded_fields_length_without_bloom and rlp_encode_fields_without_bloom
duplicate pattern-matching across receipt variants; refactor them to call
as_receipt() like rlp_encoded_fields_length and rlp_encode_fields do: replace
the match arms in rlp_encoded_fields_length_without_bloom with let r =
self.as_receipt(); then compute r.status.length() +
r.cumulative_gas_used.length() + r.logs.length(), and in
rlp_encode_fields_without_bloom call let r = self.as_receipt(); then
r.status.encode(out); r.cumulative_gas_used.encode(out); r.logs.encode(out);
ensuring you handle the existing Borrowing/inner access differences by using the
unified as_receipt() view.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/primitives/src/receipt/mod.rs`:
- Around line 131-167: The two methods rlp_encoded_fields_length_without_bloom
and rlp_encode_fields_without_bloom duplicate pattern-matching across receipt
variants; refactor them to call as_receipt() like rlp_encoded_fields_length and
rlp_encode_fields do: replace the match arms in
rlp_encoded_fields_length_without_bloom with let r = self.as_receipt(); then
compute r.status.length() + r.cumulative_gas_used.length() + r.logs.length(),
and in rlp_encode_fields_without_bloom call let r = self.as_receipt(); then
r.status.encode(out); r.cumulative_gas_used.encode(out); r.logs.encode(out);
ensuring you handle the existing Borrowing/inner access differences by using the
unified as_receipt() view.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9c967feb-8756-42ce-bbeb-bfbdea3c0aba

📥 Commits

Reviewing files that changed from the base of the PR and between 5accf48 and 79f73f5.

📒 Files selected for processing (5)
  • crates/consensus/src/error.rs
  • crates/evm/src/block/mod.rs
  • crates/primitives/src/receipt/mod.rs
  • crates/revm/src/token_fee.rs
  • crates/revm/src/tx.rs
✅ Files skipped from review due to trivial changes (1)
  • crates/revm/src/tx.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/evm/src/block/mod.rs
  • crates/revm/src/token_fee.rs

@panos-xyz panos-xyz requested a review from chengwenxi March 23, 2026 14:02
@chengwenxi
Copy link
Copy Markdown
Contributor

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@chengwenxi chengwenxi merged commit b246b10 into main Mar 25, 2026
9 checks passed
@chengwenxi chengwenxi deleted the refactor/simplify-crates branch March 25, 2026 02:42
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