Skip to content

Conversation

joaquim-verges
Copy link
Member

@joaquim-verges joaquim-verges commented Oct 1, 2025

Summary by CodeRabbit

  • Bug Fixes
    • Corrected minimal-account detection to consider a configured delegation contract, ensuring accurate authorization behavior for delegated EOAs, including batched transactions. Behavior remains unchanged when no delegation is set.
  • Refactor
    • Enhanced authorization caching to include delegation context, improving correctness and reducing unnecessary rechecks.
  • Tests
    • Expanded integration tests to cover delegation-aware flows and assertions.
  • Chores
    • Removed unused imports and example constants to reduce noise and improve maintainability.

Copy link

coderabbitai bot commented Oct 1, 2025

Walkthrough

The change introduces delegation-aware minimal-account checks across core, executors, server, and tests. A new optional delegation contract parameter is threaded through DelegatedAccount and EoaAuthorizationCache, updating cache keys and call sites. Constants cleanup removes unused imports. Integration tests now supply delegation contract context.

Changes

Cohort / File(s) Summary
Constants cleanup
eip7702-core/src/constants.rs
Removed unused Address imports and a commented example constant. No public API changes.
Delegated account API
eip7702-core/src/delegated_account.rs
DelegatedAccount::is_minimal_account now takes Option<Address> for delegation contract and returns delegation-aware result. Updated logging.
Transaction minimal check
eip7702-core/src/transaction.rs
Passes Some(delegation_contract) to is_minimal_account; early-return behavior now delegation-aware.
Integration tests update
eip7702-core/tests/integration_tests.rs
Tests retrieve and pass delegation contract to minimal checks and authorization flow; assertions aligned with delegated state.
Authorization cache expansion
executors/src/eoa/authorization_cache.rs
Cache key extended with delegation_contract: Address. is_minimal_account now accepts Option<Address>, threads it to cache and delegated account.
Worker call-site update
executors/src/eoa/worker/mod.rs
Updated call to authorization_cache.is_minimal_account(&delegated_account, None).
Server router call-site update
server/src/execution_router/mod.rs
Adjusted call to pass None to is_minimal_account in EOA path.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller as Caller (Worker/Server/Tx)
  participant Cache as EoaAuthorizationCache
  participant DA as DelegatedAccount
  note over Caller,DA: Delegation-aware minimal-account check

  Caller->>Cache: is_minimal_account(&DelegatedAccount, delegation_contract: Option<Address>)
  Cache->>Cache: Build key {eoa, chain, delegation_contract or ZERO}
  alt Cache hit
    Cache-->>Caller: cached is_minimal
  else Cache miss
    Cache->>DA: is_minimal_account(delegation_contract)
    DA-->>Cache: is_minimal (delegation-aware)
    Cache->>Cache: Store result under expanded key
    Cache-->>Caller: is_minimal
  end
Loading
sequenceDiagram
  autonumber
  actor Tx as Transaction Flow
  participant DA as DelegatedAccount

  note over Tx,DA: Authorization decision based on delegation-aware minimal check
  Tx->>DA: is_minimal_account(Some(delegation_contract))
  alt Minimal with respect to delegation
    Tx-->>Tx: Early return (no auth added)
  else Not minimal
    Tx-->>Tx: Proceed to add authorization
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title accurately and concisely captures the primary change introduced by the pull request, namely adding delegation contract verification for EIP-7702 accounts, without extraneous details or generic wording.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch Add_delegation_contract_verification_for_EIP-7702_accounts

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • EIP-7702: Entity not found: Issue - Could not find referenced Issue.

Comment @coderabbitai help to get the list of available commands and usage tips.

@joaquim-verges joaquim-verges marked this pull request as ready for review October 1, 2025 19:51
Copy link
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

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)
eip7702-core/tests/integration_tests.rs (1)

660-664: Fix panic before fetching delegation contract

setup.delegation_contract is still None immediately after TestSetup::new(). Calling expect here will panic and fail the test before any delegation setup occurs. Fetch the bytecode (which populates the contract) before unwrapping the option.

 let mut setup = TestSetup::new().await?;
-let delegation_contract = setup.delegation_contract.expect("Delegation contract should be set");
-
-// Step 1: Fetch and set bytecode from Base Sepolia
-setup.fetch_and_set_bytecode().await?;
+// Step 1: Fetch and set bytecode from Base Sepolia
+setup.fetch_and_set_bytecode().await?;
+
+let delegation_contract = setup.delegation_contract.expect("Delegation contract should be set");
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • 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 a23171c and 347b5d5.

📒 Files selected for processing (7)
  • eip7702-core/src/constants.rs (0 hunks)
  • eip7702-core/src/delegated_account.rs (2 hunks)
  • eip7702-core/src/transaction.rs (1 hunks)
  • eip7702-core/tests/integration_tests.rs (4 hunks)
  • executors/src/eoa/authorization_cache.rs (2 hunks)
  • executors/src/eoa/worker/mod.rs (1 hunks)
  • server/src/execution_router/mod.rs (1 hunks)
💤 Files with no reviewable changes (1)
  • eip7702-core/src/constants.rs
🧰 Additional context used
🧬 Code graph analysis (2)
eip7702-core/src/delegated_account.rs (1)
executors/src/eoa/authorization_cache.rs (1)
  • is_minimal_account (25-41)
eip7702-core/tests/integration_tests.rs (2)
eip7702-core/src/delegated_account.rs (1)
  • is_minimal_account (31-85)
executors/src/eoa/authorization_cache.rs (1)
  • is_minimal_account (25-41)
🔇 Additional comments (2)
eip7702-core/src/delegated_account.rs (2)

76-82: Debug logging looks comprehensive.

The updated trace includes all relevant context: EOA address, target address extracted from bytecode, the delegation contract being checked against, and the final delegation status.


31-31: Confirm and clarify None behavior for delegation_contract
All call sites now pass the new parameter, but several (in execution_router and worker) use None, causing is_minimal_account(None) to unconditionally return true and the cache to key on Address::ZERO. Verify this fallback matches intended semantics or require callers to supply an explicit delegation_contract.

Comment on lines +67 to +74
let is_delegated = match delegation_contract {
Some(delegation_contract) => {
target_address == delegation_contract
}
None => {
true
}
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Reconsider the None case returning true by default.

When delegation_contract is None, the method returns true (assumes delegation exists), which seems semantically incorrect. This means "I don't know which contract to check against, so I'll assume it's delegated."

Additionally, the authorization cache (shown in relevant snippets) uses Address::ZERO as a fallback when delegation_contract is None, which could lead to cache key collisions—different delegation contracts would share the same cache entry.

Consider either:

  • Returning an error when delegation_contract is None and delegation verification is actually needed
  • Making delegation_contract a required parameter instead of Option<Address>
  • Documenting clearly why None means "assume delegated"

Run the following script to understand how None is used across the codebase:


🏁 Script executed:

#!/bin/bash
# Description: Find all call sites passing None to is_minimal_account

# Search for calls with None argument
rg -n -B 5 -A 3 '\.is_minimal_account\(\s*None\s*\)' --type rust

# Also check cache usage with Address::ZERO
rg -n -B 3 -A 3 'Address::ZERO' --type rust -g '*authorization_cache*'

Length of output: 672


🏁 Script executed:

#!/bin/bash
# 1. Find definition of is_minimal_account
rg -n 'fn is_minimal_account' -C3 --type rust

# 2. Show lines 60-100 in delegated_account.rs to inspect None handling
sed -n '60,100p' eip7702-core/src/delegated_account.rs

# 3. Show lines 1-100 in authorization_cache.rs for call-site context
sed -n '1,100p' executors/src/eoa/authorization_cache.rs

Length of output: 3615


Reconsider default behavior when delegation_contract is None.

  • In DelegatedAccount::is_minimal_account (eip7702-core/src/delegated_account.rs:67–74), returning true on None unconditionally bypasses the delegation check—any call without a contract will always succeed. Instead, either require a valid delegation_contract or return an error when it’s missing.
  • In EoaAuthorizationCache (executors/src/eoa/authorization_cache.rs:35–38), using unwrap_or(Address::ZERO) for the cache key collapses all None cases into the same entry, risking collisions. Consider encoding the Option directly in the key or using a distinct sentinel for “no contract.”
🤖 Prompt for AI Agents
In eip7702-core/src/delegated_account.rs around lines 67–74 and
executors/src/eoa/authorization_cache.rs around lines 35–38, the current logic
treats a missing delegation_contract as a successful delegation and collapses
all None cases into Address::ZERO for cache keys; update
DelegatedAccount::is_minimal_account to not unconditionally return true when
delegation_contract is None — either require Some and return false (or propagate
an Err) when it’s missing and adjust the function signature/call sites
accordingly so callers handle the missing contract explicitly; in
EoaAuthorizationCache stop using unwrap_or(Address::ZERO) — change the cache key
to encode the Option (e.g., use Option<Address> or a (bool, Address) tuple) or
choose a distinct sentinel value and document it to avoid collisions so each
None vs Some(contract) is cached separately.

@d4mr d4mr merged commit ac2ecf3 into main Oct 1, 2025
4 checks passed
@d4mr d4mr deleted the Add_delegation_contract_verification_for_EIP-7702_accounts branch October 1, 2025 21:00
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