fix(levm): account erroneously considered as existing after zero-value transfer#6591
Conversation
A zero-value increase/decrease_account_balance call would touch the account via mark_modified, setting account.exists = true even though no real change occurred. A subsequent EIP-7702 SetCode tx in the same block whose authority is that address would then see exists = true and apply the spurious REFUND_AUTH_PER_EXISTING_ACCOUNT. This test compares the gas charged by an EIP-7702 SetCode tx with a fresh authority in two scenarios within a single block: only the EIP-7702 tx, and a 0-value transfer to the authority followed by the EIP-7702 tx. Both must charge the same gas.
🤖 Kimi Code ReviewOverall Assessment:
|
Greptile SummaryThis PR fixes a bug where sending a zero-value transfer to an empty account would incorrectly mark that account as "existing" in the VM's cache, causing EIP-7702 gas to be charged at the wrong (lower) rate in a subsequent
Confidence Score: 5/5Safe to merge — the change is a small, targeted early-return that removes an unintended side effect, covered by a new end-to-end integration test. The fix is minimal and well-scoped: two identical early-return guards added to functions that previously had no callers relying on the zero-value side-effect. The existing transfer wrapper already skipped both calls for zero values, so the only paths affected are direct callers that did not have their own guard. The new integration test directly validates the gas difference that motivated the bug report. No files require special attention.
|
| Filename | Overview |
|---|---|
| crates/vm/levm/src/db/gen_db.rs | Adds zero-value short-circuit guards to increase_account_balance and decrease_account_balance, preventing spurious account loads that were corrupting EIP-7702 existence tracking. |
| test/tests/blockchain/eip7702_zero_transfer_tests.rs | New integration test that validates the zero-value transfer does not pollute the EIP-7702 authority existence flag by comparing gas used in two scenarios. |
| test/tests/blockchain/mod.rs | Registers the new test module; trivial one-line addition. |
Reviews (1): Last reviewed commit: "do not mark the account as modified when..." | Re-trigger Greptile
Lines of code reportTotal lines added: Detailed view |
🤖 Codex Code ReviewNo findings. The change in gen_db.rs and gen_db.rs looks correct: skipping I couldn’t run the new test locally: Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
🤖 Claude Code ReviewNow I have everything I need. Here is the full review: PR #6591 —
|
Benchmark Results ComparisonNo significant difference was registered for any benchmark run. Detailed ResultsBenchmark Results: BubbleSort
Benchmark Results: ERC20Approval
Benchmark Results: ERC20Mint
Benchmark Results: ERC20Transfer
Benchmark Results: Factorial
Benchmark Results: FactorialRecursive
Benchmark Results: Fibonacci
Benchmark Results: FibonacciRecursive
Benchmark Results: ManyHashes
Benchmark Results: MstoreBench
Benchmark Results: Push
Benchmark Results: SstoreBench_no_opt
|
**Motivation** Prepare the v12.0.0 release by bumping the workspace version and merging the release branch back to main. **Description** - Bump workspace version from 11.0.0 to 12.0.0 in the root `Cargo.toml`, the guest-program `Cargo.toml` files (sp1, risc0, openvm, zisk) and `crates/l2/tee/quote-gen/Cargo.toml`; refresh lockfiles via `make update-cargo-lock`. - Update the `--builder.extra-data` default in `docs/CLI.md` to `ethrex 12.0.0` in both ethrex and ethrex L2 sections. - Merge `main` into the release branch, picking up the two levm fixes that landed during release stabilization (lambdaclass#6591, lambdaclass#6592) along with their tests: - `fix(levm): account erroneously considered as existing after zero-value transfer` (lambdaclass#6591) — avoids marking an account as modified when a balance increase/decrease is zero. - `fix(levm): revert doesn't unmark the account as existing` (lambdaclass#6592) — `restore_cache_state` now restores `exists` alongside `info`, `status`, and `has_storage` so a reverted transaction no longer leaves a stale `exists = true` in the cache (which would cause a later EIP-7702 SetCode tx to apply a spurious `REFUND_AUTH_PER_EXISTING_ACCOUNT` / EIP-8037 `STATE_GAS_NEW_ACCOUNT` refund). Also reorders the backup in `VM::get_account_mut` and the SELFDESTRUCT hook so the backup captures pre-modification state. These fixes were also cherry-picked directly onto the release branch before the merge; the merge from `main` adds their tests. **Checklist** - [x] Updated `STORE_SCHEMA_VERSION` — N/A, no storage schema change. --------- Co-authored-by: Lucas Fiegl <iovoid@users.noreply.github.com>
…e transfer (#6591) **Motivation** When sending a zero-value transfer to an empty account, we incorrectly mark it as existing for the purposes of EIP7702, leading to charging gas incorrectly. **Description** Currently we track accounts that exist in the trie for purposes of charging EIP7702 gas (the price is different if the authority already exists in the trie). When sending a zero-value transfer to an empty account, we incorrectly mark it as existing. The PR contains a regression test, that should fail on the first commit and pass on the second.
…e transfer (#6591) **Motivation** When sending a zero-value transfer to an empty account, we incorrectly mark it as existing for the purposes of EIP7702, leading to charging gas incorrectly. **Description** Currently we track accounts that exist in the trie for purposes of charging EIP7702 gas (the price is different if the authority already exists in the trie). When sending a zero-value transfer to an empty account, we incorrectly mark it as existing. The PR contains a regression test, that should fail on the first commit and pass on the second.
**Motivation** Bring ethrex up to bal-devnet-7 (BAL fixtures `bal@v7.1.1`). Stacked on top of #bal-devnet-6-pr (now in main). **Description** Aligns EIP-8037 state-gas accounting with bal-devnet-7 spec progression (EELS PRs lambdaclass#2815 / lambdaclass#2816 / lambdaclass#2823 / lambdaclass#2827 / lambdaclass#2828 / lambdaclass#2836 / lambdaclass#2845 / lambdaclass#2848), bumps Amsterdam fixtures from `snobal-devnet-6@v1.1.0` to `bal@v7.1.1`, and bumps the pinned hive version past the ethrex `--http.api` fix. Main changes: - EIP-8037 state-gas alignment with bal-devnet-7: - System-call state-gas reservoir. - Halt refunds spilled state gas (Policy A). - Tx-level CREATE failure refunds intrinsic `NEW_ACCOUNT`; `intrinsic_state_gas_charged` preserved across the failure path. - Tx-CREATE collision refund with regular-gas burn; billing matches EELS. - Cross-frame revert leaks inline credits. - Cross-frame revert reservoir formula fix. - Block-level `state_gas_used` subtracts `state_refund`. - Remove same-tx SELFDESTRUCT state-gas refund (EELS PR lambdaclass#2845, v7.1.0). - EIP-7702: - `set_delegation` refund via dedicated `state_refund` channel. - `set_delegation` refunds `AUTH_BASE` on existing delegation (EELS PR lambdaclass#2836). - `set_delegation` refunds `AUTH_BASE` on delegation clear (EELS PR lambdaclass#2848, v7.1.1). - levm fixes pulled from main: - `revert` doesn't unmark the account as existing (lambdaclass#6592). - Account erroneously considered as existing after zero-value transfer (lambdaclass#6591). - Tooling / tests: - Per-tx gas-dimension dump on block `gas_used` mismatch. - Bump Amsterdam fixtures to `bal@v7.1.1`. - Annotate BAL balance-mismatch errors with gas-equivalent diff and recognised state-gas constant multiples. - Unskip 74 bal-devnet-6 Amsterdam fixtures now passing. - Skip 21 stale EIP-8025 fixtures pinned at `bal@v5.7.0` (zkevm@v0.3.3 bundle, pre-bal-7). - Drop stale bal-devnet-6 known-issues entries from `docs/known_issues.md` and hive `KNOWN_EXCLUDED_TESTS`. - CI: - Bump pinned hive version past the ethrex `--http.api` flag feature-detect fix (`c4d839b3`, hive lambdaclass#1485). Without this, hive starts ethrex with the default HTTP namespace allowlist (`eth,net,web3`) and tests touching `admin_*`/`debug_*`/`txpool_*` fail. **Local test run** `./run_test.sh` against `tests-bal@v7.1.1`: 2,145 / 2,145 pass. `cargo test -p ethrex-test --tests`: 453 / 453 pass. **Checklist** - [ ] Updated `STORE_SCHEMA_VERSION` (crates/storage/lib.rs) if the PR includes breaking changes to the `Store` requiring a re-sync. --------- Co-authored-by: Lucas Fiegl <iovoid@users.noreply.github.com> Co-authored-by: Ivan Litteri <67517699+ilitteri@users.noreply.github.com>
Motivation
When sending a zero-value transfer to an empty account, we incorrectly mark it as existing for the purposes of EIP7702, leading to charging gas incorrectly.
Description
Currently we track accounts that exist in the trie for purposes of charging EIP7702 gas (the price is different if the authority already exists in the trie).
When sending a zero-value transfer to an empty account, we incorrectly mark it as existing.
The PR contains a regression test, that should fail on the first commit and pass on the second.