Skip to content

Conversation

@madisoncarter1234
Copy link
Contributor

Summary

  • Add comprehensive tests for EIP-7702 authorization/delegation transactions in pending/flashblocks state
  • 3 tests pass, 1 test exposes overflow bug at state.rs:558
  • This surfaces the sporadic behavior reported by users

Test plan

  • cargo test --package base-reth-rpc --test eip7702_tests

Closes #279

@cb-heimdall
Copy link
Collaborator

cb-heimdall commented Dec 15, 2025

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1

@madisoncarter1234 madisoncarter1234 force-pushed the test/eip7702-pending-state branch 3 times, most recently from 7819e69 to 4b7efcf Compare December 15, 2025 03:01
use rollup_boost::{ExecutionPayloadBaseV1, ExecutionPayloadFlashblockDeltaV1};

// Test accounts from test_utils (Anvil deterministic keys)
const ALICE_ADDRESS: Address = address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
Copy link
Contributor

Choose a reason for hiding this comment

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

use self.harness.accounts instead of hardcoding accounts here

const BOB_PRIVATE_KEY: &str = "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";

// Counter contract address (deployed in test payloads)
const COUNTER_ADDRESS: Address = address!("e7f1725e7734ce288f8367e1bb143e90bb3f0512");
Copy link
Contributor

Choose a reason for hiding this comment

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

instead of hardcoding, make this part of the TestSetup. The address will change if new transactions were added at some point before the contract deployment as the nonce change will cause the contract address to change.

You can take a look at https://github.com/madisoncarter1234/node-reth/blob/4b7efcf0b8ddbfecf5d62c806976d8f534d34f86/crates/rpc/tests/eth_call_erc20.rs#L37 for reference

const COUNTER_ADDRESS: Address = address!("e7f1725e7734ce288f8367e1bb143e90bb3f0512");

// Function selectors
const INCREMENT_SELECTOR: [u8; 4] = [0xd0, 0x9d, 0xe0, 0x8a]; // increment()
Copy link
Contributor

@haardikk21 haardikk21 Dec 15, 2025

Choose a reason for hiding this comment

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

You should be able to get this from the autogenerated contract bindings as well. im away from my computer right now but the syntax is something like ContractName::incrementCall {}::abi_encode() or something

Just want to avoid hardcoding stuff like this as much as possible

}

/// Create a signer from a hex-encoded private key
fn create_signer(private_key: &str) -> PrivateKeySigner {
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldnt be needed once you switch to harness.accounts

setup.send_flashblock(base_payload).await?;

// Create authorization for Alice to delegate to COUNTER_ADDRESS
let auth = build_authorization(chain_id, COUNTER_ADDRESS, 0, ALICE_PRIVATE_KEY);
Copy link
Contributor

@haardikk21 haardikk21 Dec 15, 2025

Choose a reason for hiding this comment

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

This is a bit confusing. Why is Alice delegating to a Counter contract?

I would much prefer a new contract to be created if necessary - something like Minimal7702Account.sol or something - with autogenerated sol! bindings. Even if functionally it behaves similarly, it will help a lot with readability and understanding what's going on, plus if we do some actual 7702 wallet style code in the contract we should be able to then test some more smart-wallet-esque features as well (e.g. multicalls like appprove+transferFrom in a single txn)

@madisoncarter1234 madisoncarter1234 force-pushed the test/eip7702-pending-state branch from 4b7efcf to eb70b58 Compare December 15, 2025 14:42
  pending state

  Add tests for EIP-7702 authorization and delegation transactions in
   pending/flashblocks state per base#279.

  Tests:
  - Single delegation in pending flashblock
  - Multiple delegations in same flashblock
  - Receipt retrieval for EIP-7702 transactions
  - Delegation followed by execution across flashblocks

  test_eip7702_delegation_then_execution fails with overflow at
  state.rs:558 - this surfaces the sporadic behavior users reported.

  Closes base#279
@madisoncarter1234 madisoncarter1234 force-pushed the test/eip7702-pending-state branch from eb70b58 to 0a0336d Compare December 15, 2025 15:11
Comment on lines +379 to +384
/// Test EIP-7702 delegation followed by execution in subsequent flashblock.
///
/// NOTE: This test is ignored because it surfaces a bug in the flashblocks processor
/// (overflow at processor.rs:472). This demonstrates the sporadic behavior reported
/// in issue #279. The test should be un-ignored once the underlying bug is fixed.
#[tokio::test]
Copy link
Contributor

Choose a reason for hiding this comment

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

Have you had a chance to dig into what the bug is and why it happens? It should probably be fixed as part of this PR if its not too crazy. I can also try taking a look later this week if its not straightforward

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Have you had a chance to dig into what the bug is and why it happens? It should probably be fixed as part of this PR if its not too crazy. I can also try taking a look later this week if its not straightforward

the problem is at processor.rs:472: gas_used: receipt.cumulative_gas_used() - gas_used, When multiple flashblocks belong to the same block, all their transactions get processed together with gas_used starting at 0.

the problem is the subtraction assumes cumulative gas values are monotonically increasing across all transactions in the block. In the test case (test_eip7702_delegation_then_execution), flashblock index 1 has cumulative 30000 and flashblock index 2 has cumulative 25000 - both for block 1.

So when processing:

  • tx1: 30000 - 0 = 30000 ✓
  • tx2: 25000 - 30000 = underflow

the fix is simple, just need to use saturating_sub or checked_sub there. adding to the pr

Copy link
Contributor

Choose a reason for hiding this comment

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

That is not a 7702 bug then but rather the test is incorrect as it's not supplying cumulative gas usage correctly. Flashblock cumulative gas usage values must persist across flashblocks belonging to the same block. eceipt.cumulative_gas_used() - gas_used should never be underflowing

Use saturating_sub instead of subtraction when calculating per-transaction
gas from cumulative gas values. When multiple flashblocks belong to the
same block, subsequent flashblocks may have lower cumulative gas values
than earlier ones, causing an arithmetic underflow.

Fixes base#279
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.

add EIP-7702 delegation tests for flashblocks rpc

3 participants