Skip to content

feat(l1): reject contract senders at mempool admission (EIP-3607)#6600

Open
ilitteri wants to merge 7 commits into
mainfrom
feat/mempool-eip3607-sender-check
Open

feat(l1): reject contract senders at mempool admission (EIP-3607)#6600
ilitteri wants to merge 7 commits into
mainfrom
feat/mempool-eip3607-sender-check

Conversation

@ilitteri
Copy link
Copy Markdown
Collaborator

Motivation

Every major Ethereum execution client enforces EIP-3607: transactions whose recovered sender has deployed code are rejected, except where the code is an EIP-7702 delegation designation (the account is still an EOA in spirit, just pointing at delegate code). Without this check, contract accounts can submit invalid transactions that waste pool space and gossip bandwidth.

Description

  • New helper is_eip7702_delegation(code: &[u8]) -> bool plus EIP7702_DELEGATION_PREFIX = 0xef0100 and EIP7702_DELEGATED_CODE_LEN = 23 constants in crates/common/types/account.rs.
  • Blockchain::validate_transaction now inspects the sender's code_hash; if non-empty, it fetches the code (a single extra store hit only when the sender actually has code) and routes through is_eip7702_delegation. Non-delegation contract senders are rejected with the new MempoolError::SenderIsContract.
  • Six unit tests for the delegation predicate covering: empty, valid 23-byte designation, too-short, too-long, wrong-prefix, and arbitrary contract code.

Adds the EIP-3607 sender check that every major Ethereum execution
client (geth, reth, nethermind, erigon, besu) enforces. Transactions
whose recovered sender has deployed code are rejected, except where the
code is a valid EIP-7702 delegation designation (the account is still
an EOA in spirit, just pointing at delegate code).

- New helper `is_eip7702_delegation(code: &[u8]) -> bool` plus
  `EIP7702_DELEGATION_PREFIX = 0xef0100` and `EIP7702_DELEGATED_CODE_LEN
  = 23` constants in `crates/common/types/account.rs`.
- `Blockchain::validate_transaction` now inspects the sender's
  `code_hash`; if non-empty, it fetches the code (single extra store
  hit only when the sender actually has code) and routes through
  `is_eip7702_delegation`. Non-delegation contract senders are rejected
  with the new `MempoolError::SenderIsContract`.
- Six unit tests for the delegation predicate covering: empty, valid
  23-byte designation, too-short, too-long, wrong-prefix, and arbitrary
  contract code.
Copilot AI review requested due to automatic review settings May 11, 2026 19:23
@ilitteri ilitteri requested a review from a team as a code owner May 11, 2026 19:23
@github-actions github-actions Bot added the L1 Ethereum client label May 11, 2026
@github-actions
Copy link
Copy Markdown

🤖 Kimi Code Review

Overall Assessment: The PR correctly implements EIP-3607 (rejecting transactions from accounts with code) with the proper EIP-7702 delegation exception. The logic is sound and well-tested, but there's a typo in the imported constant name.

Issues Found

1. Typo in constant name (Critical)

File: crates/blockchain/blockchain.rs, line 60
Issue: EMPTY_KECCACK_HASH should be EMPTY_KECCAK_HASH (double 'C' vs single 'C'). If the constant is defined elsewhere with the correct spelling, this will fail to compile. If the constant is defined with the typo, it should be fixed in the constants module as well.

// Current (incorrect):
use ethrex_common::constants::{EMPTY_KECCACK_HASH, ...};

// Should be:
use ethrex_common::constants::{EMPTY_KECCAK_HASH, ...};

2. Unnecessary database read for common case (Minor/Performance)

File: crates/blockchain/blockchain.rs, lines 2498-2503
Issue: The code fetches full account code from storage even though most transactions come from EOAs (empty code). While correct, this adds a storage lookup for the minority case of contracts.

Suggestion: The check is unavoidable for correctness, but ensure the storage layer efficiently handles cache misses for the empty code case.

3. Error propagation clarity

File: crates/blockchain/blockchain.rs, line 2501
Issue: The Err(e.into()) conversion could obscure the specific storage error type in logs. Consider whether MempoolError preserves the underlying storage error context for debugging.

Positive Feedback

  1. Correct EIP-7702 implementation: The delegation prefix 0xef0100 and length check (23 bytes) in crates/common/types/account.rs (lines 194-202) accurately follow the specification.

  2. Comprehensive test coverage: The tests for is_eip7702_delegation cover valid delegations, empty code, incorrect lengths, wrong prefixes, and arbitrary contract code.

  3. Proper mempool validation: EIP-3607 is correctly enforced as a mempool rule (not consensus), rejecting transactions from contract accounts while allowing the EIP-7702 exception.

  4. Code clarity: The logic flow is clear—checking nonce first, then EIP-3607 compliance, then transaction costs is a reasonable ordering for early rejection of invalid transactions.

Recommendation

Fix the EMPTY_KECCAK_HASH typo before merging. The implementation is otherwise correct and secure.


Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 11, 2026

Lines of code report

Total lines added: 67
Total lines removed: 4
Total lines changed: 71

Detailed view
+----------------------------------------+-------+------+
| File                                   | Lines | Diff |
+----------------------------------------+-------+------+
| ethrex/crates/blockchain/blockchain.rs | 2532  | +24  |
+----------------------------------------+-------+------+
| ethrex/crates/blockchain/error.rs      | 151   | +4   |
+----------------------------------------+-------+------+
| ethrex/crates/common/types/account.rs  | 366   | +39  |
+----------------------------------------+-------+------+
| ethrex/crates/vm/levm/src/utils.rs     | 457   | -4   |
+----------------------------------------+-------+------+

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 11, 2026

Greptile Summary

This PR implements EIP-3607 mempool admission enforcement: transactions from senders with deployed code are rejected unless that code is an EIP-7702 delegation designation (0xef0100 || address), preserving the "EOA in spirit" carve-out introduced in Prague.

  • is_eip7702_delegation is added as a pure predicate in account.rs with two exported constants matching the EIP-7702 spec (3-byte prefix + 20-byte address = 23 bytes total); six unit tests cover all boundary cases.
  • validate_transaction in blockchain.rs checks the sender's code_hash and only calls into storage when the hash is non-empty, keeping the fast path zero-cost for normal EOAs; a missing code entry (Ok(None)) is treated conservatively as non-delegation and causes rejection.
  • MempoolError::SenderIsContract is added to error.rs with a clear EIP-3607 attribution.

Confidence Score: 5/5

Safe to merge — the change is self-contained, correctly implements the spec, and the fast path for normal EOAs is untouched.

The predicate logic matches the EIP-7702 wire format exactly, the unit tests cover all edge cases (empty, valid, too-short, too-long, wrong prefix, arbitrary bytecode), the storage call is only made when necessary, and the conservative Ok(None) handling is appropriate for mempool admission. No correctness issues found.

No files require special attention.

Important Files Changed

Filename Overview
crates/common/types/account.rs Adds is_eip7702_delegation predicate, EIP7702_DELEGATION_PREFIX, and EIP7702_DELEGATED_CODE_LEN constants; six unit tests cover all boundary cases (empty, valid, short, long, wrong prefix, arbitrary code). Logic and constants match the EIP-7702 spec exactly.
crates/blockchain/blockchain.rs Adds EIP-3607 check inside validate_transaction: inspects sender's code_hash, fetches bytecode only when non-empty, and routes through is_eip7702_delegation; non-delegation contract senders are rejected. Storage call is correctly synchronous and the check is correctly placed within the existing sender_acc_info guard.
crates/blockchain/error.rs Adds SenderIsContract variant to MempoolError with a descriptive error message referencing EIP-3607.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[validate_transaction] --> B[Get sender account info]
    B --> C{Account exists?}
    C -- No --> D[Return NotEnoughBalance]
    C -- Yes --> E{code_hash == EMPTY_KECCACK_HASH?}
    E -- Yes: EOA, no code --> F[Skip EIP-3607 check]
    E -- No: account has code --> G[get_account_code from storage]
    G --> H{Code found?}
    H -- Ok None: DB inconsistency --> I[is_delegation = false]
    H -- Err --> J[Return StoreError]
    H -- Ok Some code --> K[is_eip7702_delegation check]
    K --> L{Starts with 0xef0100 AND len == 23?}
    L -- Yes --> M[is_delegation = true]
    L -- No --> I
    M --> N[Allow: EIP-7702 carve-out]
    I --> O[Return SenderIsContract]
    F --> P[Continue balance & nonce checks]
    N --> P
Loading

Reviews (1): Last reviewed commit: "feat(l1): reject contract senders at mem..." | Re-trigger Greptile

@github-actions
Copy link
Copy Markdown

🤖 Claude Code Review

Now I have enough context. Here's the review:


PR Review: feat(l1): reject contract senders at mempool admission (EIP-3607)

Summary

The implementation is correct and well-structured. The EIP-3607 check is placed at the right point in validate_transaction, the predicate logic is exact per spec, and the six unit tests cover the boundary cases thoroughly. A few issues are worth addressing before merge.


Issues

1. Constant/predicate duplication — the new common definition is not yet canonical

This PR adds the third independent definition of the same magic bytes and length:

Location Bytes constant Length constant Predicate
crates/vm/levm/src/constants.rs:86 SET_CODE_DELEGATION_BYTES EIP7702_DELEGATED_CODE_LEN utils::code_has_delegation
crates/l2/networking/rpc/l2/transaction.rs:18-19 DELGATION_PREFIX (typo) EIP7702_DELEGATED_CODE_LEN inline check
crates/common/types/account.rs:196-204 (new) EIP7702_DELEGATION_PREFIX EIP7702_DELEGATED_CODE_LEN is_eip7702_delegation

Placing the canonical definition in ethrex_common is exactly the right move. But since the levm and L2 RPC paths weren't updated, the three copies can now drift. A future change to the magic bytes (unlikely but not impossible during protocol development) would need to be applied in three places. At minimum, levm/src/utils.rs:code_has_delegation should call is_eip7702_delegation from ethrex_common rather than re-implementing it:

// levm/src/utils.rs
pub fn code_has_delegation(code: &Bytes) -> Result<bool, VMError> {
    Ok(is_eip7702_delegation(code.as_ref()))
}

The l2/networking/rpc/l2/transaction.rs inline check (which also has the DELGATION_PREFIX typo) should use the common function too.


2. Ok(None) branch silently rejects rather than surfacing an inconsistency

blockchain.rs:2501:

Ok(None) => false,

If code_hash != EMPTY_KECCACK_HASH but the code body is absent from storage, that is a database inconsistency — a hash references code that isn't there. Treating it as is_delegation = false causes the TX to be rejected with SenderIsContract, which is misleading. Returning a storage error would be more appropriate, or at least a distinct error variant. At minimum add a comment explaining the intentional "fail safe" choice so a future reader doesn't try to "fix" it by returning Ok(()).


3. Missing integration-level test for the rejection path

The six unit tests verify is_eip7702_delegation thoroughly, but there's no test that actually exercises the validate_transaction path with a contract-sender account. A regression could remove the guard and the unit tests would still pass. Consider adding a test that sets up a mempool with a sender whose code_hash is non-empty and verifies MempoolError::SenderIsContract is returned.


Minor observations

  • The chain_id validation check at blockchain.rs:2527 comes after the EIP-3607 check. A transaction with an invalid chain ID from a contract sender will surface SenderIsContract rather than InvalidChainId. This is not incorrect (rejecting early is fine), but if error message fidelity matters for RPC clients it's worth noting.

  • EMPTY_KECCACK_HASH (misspelling of KECCAK) is pre-existing and not introduced here, but since this PR already touches the import line it would be a natural opportunity to rename it. Not a blocker.

  • The is_eip7702_delegation function signature (&[u8] -> bool) is cleaner than the levm equivalent (&Bytes -> Result<bool, VMError>), where the Result is never actually Err in practice because the length guard precedes the slice access.


Verdict

Correct behavior, good test coverage of the predicate, and appropriate placement in the common crate. The main ask before merge is addressing the duplication (Item 1) — either update the levm/L2 callers to use the new common function, or open a tracking issue for the follow-up and note it in the PR description. Item 2 (the Ok(None) semantics) deserves at least a comment.


Automated review by Claude (Anthropic) · sonnet · custom prompt

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds EIP-3607 enforcement at mempool admission by rejecting transactions whose recovered sender has deployed code, while allowing the EIP-7702 “delegation designation” bytecode pattern as an exception.

Changes:

  • Introduces an is_eip7702_delegation(code: &[u8]) -> bool helper plus constants for the EIP-7702 delegation prefix/length.
  • Adds MempoolError::SenderIsContract and wires sender-code checks into Blockchain::validate_transaction.
  • Adds unit tests validating the delegation predicate against several edge cases.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
crates/common/types/account.rs Adds EIP-7702 delegation predicate/constants and unit tests for delegation bytecode detection.
crates/blockchain/error.rs Adds a dedicated mempool error variant for EIP-3607 contract-sender rejection.
crates/blockchain/blockchain.rs Enforces EIP-3607 at mempool validation time, with an EIP-7702 delegation exception by inspecting sender code.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/blockchain/blockchain.rs Outdated
Comment on lines +2499 to +2501
let is_delegation = match self.storage.get_account_code(sender_acc_info.code_hash) {
Ok(Some(code)) => is_eip7702_delegation(code.bytecode.as_ref()),
Ok(None) => false,
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Comment thread crates/blockchain/blockchain.rs Outdated
Comment on lines +2499 to +2504
let is_delegation = match self.storage.get_account_code(sender_acc_info.code_hash) {
Ok(Some(code)) => is_eip7702_delegation(code.bytecode.as_ref()),
Ok(None) => false,
Err(e) => return Err(e.into()),
};
if !is_delegation {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Comment thread crates/blockchain/blockchain.rs Outdated
Comment on lines +2495 to +2507
// EIP-3607: reject txs from senders with deployed code, unless the
// code is an EIP-7702 delegation designation (the account is still
// an EOA in spirit, just pointing at delegate code).
if sender_acc_info.code_hash != *EMPTY_KECCACK_HASH {
let is_delegation = match self.storage.get_account_code(sender_acc_info.code_hash) {
Ok(Some(code)) => is_eip7702_delegation(code.bytecode.as_ref()),
Ok(None) => false,
Err(e) => return Err(e.into()),
};
if !is_delegation {
return Err(MempoolError::SenderIsContract);
}
}
@github-actions
Copy link
Copy Markdown

🤖 Codex Code Review

  1. crates/blockchain/blockchain.rs misclassifies missing code blobs as SenderIsContract. The new branch does Ok(None) => false, then rejects the tx at line 2505. That is not equivalent to execution: the VM path treats a non-empty code_hash with missing code as a DB error at crates/blockchain/vm.rs:216. On a partially healed/snap-synced node, or with any code DB inconsistency, a real EIP-7702 delegated sender can be falsely rejected as “contract account” instead of surfacing storage corruption/incompleteness. This branch should propagate an error rather than folding None into “not a delegation”.

No other obvious correctness, gas-accounting, or EVM-consensus issues stood out in the diff. I couldn’t run Rust tests here because cargo needs writable ~/.cargo / git dependency fetches, which are blocked in this sandbox.


Automated review by OpenAI Codex · gpt-5.4 · custom prompt

Comment thread crates/common/types/account.rs
Comment thread crates/blockchain/blockchain.rs Outdated
ilitteri added 4 commits May 11, 2026 19:21
Replaces the `match get_account_code` block with the idiomatic
`?`-chain + `is_some_and`. Same semantics, no behavior change: error
propagation via `?`, `Ok(None)` (code-hash set but code body missing —
state inconsistency) remains a "not a delegation" result and falls
through to the `SenderIsContract` rejection, which is the conservative
choice peer clients also make. Doc-comment updated to document this
intent explicitly so a future "fix" doesn't accidentally admit
inconsistent storage.

Follow-up not in this PR: a full integration test of
`validate_transaction → SenderIsContract` requires seeding sender
state (AccountInfo + code) via `apply_account_updates_batch`, which the
test scaffolding in `test/tests/blockchain/mempool_tests.rs` doesn't
currently do. The six unit tests of `is_eip7702_delegation` already
cover the byte-level predicate; the six-line wire-up here is visually
verifiable.
Copilot + @MegaRedHand flagged that `validate_transaction` decodes the
sender's full bytecode via `get_account_code` for any non-empty
`code_hash` just to conclude "not a delegation". For large contracts
this is a wasted DB hit on every admission.

Use `Store::get_code_metadata` (which the storage layer already
exposes for length lookups) to fast-reject any code whose length is
not exactly `EIP7702_DELEGATED_CODE_LEN` (23 bytes) — those cannot
encode the `0xef0100 || address` delegation designation. Only when
the metadata length matches do we fetch + verify the prefix.
…607 path

Copilot + @codex review: when `code_hash` is non-empty but the bytecode
is missing from the store, the previous code silently treated the
account as "not a delegation" and rejected the tx with
`SenderIsContract`. That masks an inconsistent DB state (code hash
present but code missing) and — more importantly — wrongly rejects a
valid EIP-7702-delegated EOA whenever the local copy of the
delegation bytecode happens to be absent (snapsync recovery, pruning
window, etc.). The VM path treats this same condition as a DB error.

Now: when the code metadata claims a 23-byte payload, missing bytecode
returns `StoreError::Custom("code missing for hash …")` so callers
see the real cause rather than a spurious EIP-3607 rejection.
…2_delegation

@MegaRedHand: "There are already many implementations of this." The new
`is_eip7702_delegation` predicate in `ethrex-common` duplicates the
existing levm `code_has_delegation` (and the predicate in
`utils.rs:181`).

levm's `code_has_delegation` now delegates to the common helper so
both crates exercise the same byte-level check. Signature
(`Result<bool, VMError>`) is preserved because several callers use `?`;
the result is always `Ok(_)` now since the common helper is infallible.
The `SET_CODE_DELEGATION_BYTES` / `EIP7702_DELEGATED_CODE_LEN` consts in
levm/constants.rs are retained for the in-place slicing in
`get_authorized_address_from_code` and adjacent helpers; cross-crate
constant unification can be a follow-up.
@ilitteri
Copy link
Copy Markdown
Collaborator Author

c1ed9c0 — addresses the @codex finding (#6600 (comment)). Missing code is now surfaced as StoreError instead of being silently treated as non-delegation.

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 12, 2026

Benchmark Results Comparison

No significant difference was registered for any benchmark run.

Detailed Results

Benchmark Results: BubbleSort

Command Mean [s] Min [s] Max [s] Relative
main_revm_BubbleSort 3.043 ± 0.042 3.006 3.122 1.12 ± 0.02
main_levm_BubbleSort 2.724 ± 0.036 2.703 2.824 1.00
pr_revm_BubbleSort 3.022 ± 0.031 2.990 3.084 1.11 ± 0.02
pr_levm_BubbleSort 2.758 ± 0.068 2.701 2.906 1.01 ± 0.03

Benchmark Results: ERC20Approval

Command Mean [s] Min [s] Max [s] Relative
main_revm_ERC20Approval 1.009 ± 0.056 0.978 1.166 1.02 ± 0.06
main_levm_ERC20Approval 1.039 ± 0.006 1.030 1.050 1.05 ± 0.01
pr_revm_ERC20Approval 0.989 ± 0.009 0.979 1.003 1.00
pr_levm_ERC20Approval 1.037 ± 0.011 1.026 1.058 1.05 ± 0.01

Benchmark Results: ERC20Mint

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ERC20Mint 136.8 ± 2.1 135.7 142.4 1.02 ± 0.02
main_levm_ERC20Mint 157.3 ± 1.8 155.6 161.4 1.18 ± 0.02
pr_revm_ERC20Mint 133.6 ± 0.8 132.7 135.2 1.00
pr_levm_ERC20Mint 157.3 ± 1.3 155.9 160.0 1.18 ± 0.01

Benchmark Results: ERC20Transfer

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ERC20Transfer 234.2 ± 1.4 232.8 237.2 1.00
main_levm_ERC20Transfer 259.9 ± 1.1 258.1 261.6 1.11 ± 0.01
pr_revm_ERC20Transfer 238.6 ± 16.4 231.0 284.4 1.02 ± 0.07
pr_levm_ERC20Transfer 259.4 ± 0.9 257.7 261.0 1.11 ± 0.01

Benchmark Results: Factorial

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Factorial 227.4 ± 1.8 223.0 229.2 1.00
main_levm_Factorial 249.0 ± 1.9 246.8 253.4 1.10 ± 0.01
pr_revm_Factorial 228.3 ± 0.7 227.4 229.7 1.00 ± 0.01
pr_levm_Factorial 245.1 ± 0.6 244.3 246.3 1.08 ± 0.01

Benchmark Results: FactorialRecursive

Command Mean [s] Min [s] Max [s] Relative
main_revm_FactorialRecursive 1.637 ± 0.033 1.593 1.697 1.03 ± 0.02
main_levm_FactorialRecursive 1.605 ± 0.022 1.555 1.629 1.01 ± 0.02
pr_revm_FactorialRecursive 1.637 ± 0.047 1.579 1.729 1.03 ± 0.03
pr_levm_FactorialRecursive 1.590 ± 0.016 1.565 1.613 1.00

Benchmark Results: Fibonacci

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Fibonacci 207.3 ± 1.3 205.5 210.4 1.00
main_levm_Fibonacci 227.0 ± 6.2 220.6 236.4 1.10 ± 0.03
pr_revm_Fibonacci 209.4 ± 0.7 208.2 210.7 1.01 ± 0.01
pr_levm_Fibonacci 225.8 ± 5.1 219.3 232.4 1.09 ± 0.03

Benchmark Results: FibonacciRecursive

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_FibonacciRecursive 836.5 ± 15.4 819.6 870.9 1.22 ± 0.03
main_levm_FibonacciRecursive 697.4 ± 5.7 685.1 705.9 1.01 ± 0.01
pr_revm_FibonacciRecursive 852.6 ± 8.8 842.4 869.1 1.24 ± 0.02
pr_levm_FibonacciRecursive 688.3 ± 7.7 679.3 705.9 1.00

Benchmark Results: ManyHashes

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ManyHashes 8.4 ± 0.0 8.4 8.5 1.01 ± 0.01
main_levm_ManyHashes 9.8 ± 0.1 9.6 9.9 1.17 ± 0.02
pr_revm_ManyHashes 8.4 ± 0.1 8.3 8.6 1.00
pr_levm_ManyHashes 9.7 ± 0.1 9.6 9.8 1.16 ± 0.02

Benchmark Results: MstoreBench

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_MstoreBench 265.6 ± 7.5 260.1 277.3 1.16 ± 0.03
main_levm_MstoreBench 228.5 ± 0.9 227.0 230.1 1.00
pr_revm_MstoreBench 267.9 ± 4.7 262.2 277.7 1.17 ± 0.02
pr_levm_MstoreBench 235.4 ± 1.6 232.7 238.1 1.03 ± 0.01

Benchmark Results: Push

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Push 293.7 ± 1.2 292.1 295.7 1.05 ± 0.00
main_levm_Push 280.7 ± 0.5 279.9 281.3 1.00
pr_revm_Push 293.0 ± 0.7 292.0 294.0 1.04 ± 0.00
pr_levm_Push 281.3 ± 1.2 279.9 284.0 1.00 ± 0.00

Benchmark Results: SstoreBench_no_opt

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_SstoreBench_no_opt 169.0 ± 2.5 165.9 171.9 1.67 ± 0.04
main_levm_SstoreBench_no_opt 101.0 ± 2.0 99.7 105.7 1.00
pr_revm_SstoreBench_no_opt 168.2 ± 1.6 165.9 171.1 1.67 ± 0.04
pr_levm_SstoreBench_no_opt 101.1 ± 2.6 99.7 108.0 1.00 ± 0.03

Copy link
Copy Markdown
Collaborator

@MegaRedHand MegaRedHand left a comment

Choose a reason for hiding this comment

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

LGTM

Comment thread crates/blockchain/blockchain.rs Outdated
// we reject without loading the bytecode. Only when the metadata
// length matches do we fetch + verify the prefix. This avoids
// pulling potentially large contract bytecode on every contract
// sender that hits admission (Copilot / @MegaRedHand review).
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// sender that hits admission (Copilot / @MegaRedHand review).
// sender that hits admission.

Comment thread crates/blockchain/blockchain.rs Outdated
Comment on lines +2515 to +2516
// wrongly reject a valid 7702-delegated EOA per
// Copilot/@codex review).
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// wrongly reject a valid 7702-delegated EOA per
// Copilot/@codex review).
// wrongly reject a valid 7702-delegated EOA).

ilitteri and others added 2 commits May 12, 2026 17:09
Comments describe the behavior; reviewer attribution belongs in the PR
body and the commit message, not in `// ...`. Two references in
validate_transaction (one to the length pre-check rationale, one to
the missing-bytecode StoreError fallback) named the reviewers who
raised them — stripped without changing the explanations themselves.
Copy link
Copy Markdown
Contributor

@ElFantasma ElFantasma left a comment

Choose a reason for hiding this comment

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

Same TOCTOU class as #6606 / #6609 — sender state read here under no lock, add_transaction later. Two parallel submissions from a sender who becomes a contract mid-flight could both pass. The window is tiny and exploiting it requires fairly improbable timing; acceptable for now.

@github-project-automation github-project-automation Bot moved this to In Review in ethrex_l1 May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L1 Ethereum client

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

5 participants