## Summary
Two EIP-8037 state gas accounting fixes:
1. **CALL state gas ordering** — Charge new-account state gas (112 ×
cpsb = 131,488) **before** the 63/64 child gas allocation, not after
2. **Code-store OOG underflow** — Do not inflate `TotalStateGasCharged`
when `UseGas` fails for code deposit, preventing uint64 underflow in
`blockGasUsed()`
## Bug 1: CALL state gas ordering (`operations_acl.go`)
In `makeCallVariantGasCall`, the EIP-8037 state gas for new account
creation was returned in the `GasCosts` struct and charged by the
interpreter's `UseGas`/`Sub` **after** `callGas()` had already computed
the 63/64 child gas allocation using the full (pre-state-gas)
`contract.Gas.RegularGas`.
When the state gas reservoir is empty (common case — reservoir only has
gas when `tx.gasLimit` exceeds `TX_MAX_GAS_LIMIT - intrinsic`), state
gas spills to regular gas. The spill amount (131,488) far exceeds the
1/64 retained gas (~15,600 at 1M gas), causing an underflow/OOG on CALLs
that should succeed.
**Fix:** Charge state gas directly before `callGas()` so the 63/64
calculation uses the reduced regular gas, then return `StateGas: 0` to
avoid double-charging. This matches nethermind's implementation
(`EvmInstructions.Call.cs:187-213`) and besu's approach.
**Spec basis:** EIP-8037 says "State gas charges deduct from
`state_gas_reservoir` first; when the reservoir is exhausted, from
`gas_left`." The 63/64 rule applies to `gas_left`, so state gas
spillover into `gas_left` must happen before the 63/64 computation.
## Bug 2: Code-store OOG underflow (`evm.go`)
In `initNewContract`, when `UseGas` fails for code deposit (code-store
OOG on valid code), the upstream code at `evm.go:666-672` added
`createDataGas.StateGas` to `TotalStateGasCharged` without actually
consuming any gas. For a 14KB init code output, this adds ~17.3M phantom
state gas to TSC.
This inflated TSC propagates through `blockGasUsed()`:
```
execRegularUsed := totalExecUsed - execStateUsed // uint64 underflow when TSC > totalExecUsed
```
The underflow produces a massive `txRegular` value, causing
`ReturnGasAmsterdam` to reject the block with `gas limit reached`.
**Fix:** Remove the TSC inflation on `UseGas` failure (lines 666-672).
Also remove `ErrCodeStoreOutOfGas` from the `isCodeValidation` condition
(line 621-623), so code-store OOG follows the normal exceptional halt
path: all regular gas consumed, state gas reverted via
`RevertStateGas()`.
**Spec basis:** EIP-8037 §"Contract deployment cost calculation"
explicitly lists code-store OOG as a failure path:
> **Failure paths** (REVERT, OOG/invalid during initcode, **OOG during
code deposit**, or `L > MAX_CODE_SIZE`): Do NOT charge `GAS_CODE_DEPOSIT
* L` or `HASH_COST(L)`
And §"Transaction-level gas accounting":
> On child **exceptional halt**, all state gas consumed by the child,
both from the reservoir and any that spilled into `gas_left`, is
restored to the parent's reservoir.
## Test plan
- [x] geth+besu: 161 blocks (5+ epochs) with heavy spamoor load (eoatx
50 + evm-fuzz 25 + tx-fuzz 15), zero errors
- [x] Without Bug 2 fix: geth+besu chain-split at block ~30 under load —
`blockGasUsed` uint64 underflow
- [x] geth+nethermind: 86+ blocks no-load, 162 blocks eoatx load
(nethermind has separate BAL validation bug under fuzz)
- [x] geth+nimbus: 150+ blocks evm-fuzz with nimbus CALL fix applied —
gasUsed matches
- [x] Verified cross-client: nethermind and besu both charge CALL state
gas before 63/64
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Pebble maintains a batch pool to recycle the batch object. Unfortunately
batch object must be
explicitly returned via `batch.Close` function. This PR extends the
batch interface by adding
the close function and also invoke batch.Close in some critical code
paths.
Memory allocation must be measured before merging this change. What's
more, it's an open
question that whether we should apply batch.Close as much as possible in
every invocation.
For bal-devnet-3 we need to update the EIP-8024 implementation to the
latest spec changes: https://github.com/ethereum/EIPs/pull/11306
> Note: I deleted tests not specified in the EIP bc maintaining them
through EIP changes is too error prone.
Return the Amsterdam instruction set from `LookupInstructionSet` when
`IsAmsterdam` is true, so Amsterdam rules no longer fall through to the
Osaka jump table.
---------
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
This PR introduces a threshold (relative to current market base fees),
below which we suppress the diffusion of low fee transactions. Once base
fees go down, and if the transactions were not evicted in the meantime,
we release these transactions.
The PR also updates the bucketing logic to be more sensitive, removing
the extra logarithm. Blobpool description is also
updated to reflect the new behavior.
EIP-7918 changed the maximim blob fee decrease that can happen in a
slot. The PR also updates fee jump calculation to reflect this.
---------
Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
inside tx.GasPrice()/GasFeeCap()/GasTipCap() already new a big.Int.
bench result:
```
goos: darwin
goarch: arm64
pkg: github.com/ethereum/go-ethereum/core
cpu: Apple M4
│ old.txt │ new.txt │
│ sec/op │ sec/op vs base │
TransactionToMessage-10 240.1n ± 7% 175.1n ± 7% -27.09% (p=0.000 n=10)
│ old.txt │ new.txt │
│ B/op │ B/op vs base │
TransactionToMessage-10 544.0 ± 0% 424.0 ± 0% -22.06% (p=0.000 n=10)
│ old.txt │ new.txt │
│ allocs/op │ allocs/op vs base │
TransactionToMessage-10 17.00 ± 0% 11.00 ± 0% -35.29% (p=0.000 n=10)
```
benchmark code:
```
// Copyright 2025 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core
import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
// BenchmarkTransactionToMessage benchmarks the TransactionToMessage function.
func BenchmarkTransactionToMessage(b *testing.B) {
key, _ := crypto.GenerateKey()
signer := types.LatestSigner(params.TestChainConfig)
to := common.HexToAddress("0x000000000000000000000000000000000000dead")
// Create a DynamicFeeTx transaction
txdata := &types.DynamicFeeTx{
ChainID: big.NewInt(1),
Nonce: 42,
GasTipCap: big.NewInt(1000000000), // 1 gwei
GasFeeCap: big.NewInt(2000000000), // 2 gwei
Gas: 21000,
To: &to,
Value: big.NewInt(1000000000000000000), // 1 ether
Data: []byte{0x12, 0x34, 0x56, 0x78},
AccessList: types.AccessList{
types.AccessTuple{
Address: common.HexToAddress("0x0000000000000000000000000000000000000001"),
StorageKeys: []common.Hash{
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"),
},
},
},
}
tx, _ := types.SignNewTx(key, signer, txdata)
baseFee := big.NewInt(1500000000) // 1.5 gwei
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_, err := TransactionToMessage(tx, signer, baseFee)
if err != nil {
b.Fatal(err)
}
}
}
l
```
From the https://eips.ethereum.org/EIPS/eip-7928
> SELFDESTRUCT (in-transaction): Accounts destroyed within a transaction
MUST be included in AccountChanges without nonce or code changes.
However, if the account had a positive balance pre-transaction, the
balance change to zero MUST be recorded. Storage keys within the self-destructed
contracts that were modified or read MUST be included as a storage_reads
entry.
The storage read against the empty contract (zero storage) should also
be recorded in the BAL's readlist.
https://eips.ethereum.org/EIPS/eip-7928 spec:
> Precompiled contracts: Precompiles MUST be included when accessed.
If a precompile receives value, it is recorded with a balance change.
Otherwise, it is included with empty change lists.
The precompiled contracts are not explicitly touched when they are
invoked since Amsterdam fork.
In src/ethereum/forks/amsterdam/vm/interpreter.py:299-304, the caller
address is
only tracked for block level accessList when there's a value transfer:
```python
if message.should_transfer_value and message.value != 0:
# Track value transfer
sender_balance = get_account(state, message.caller).balance
recipient_balance = get_account(state, message.current_target).balance
track_address(message.state_changes, message.caller) # Line 304
```
Since system transactions have should_transfer_value=False and value=0,
this condition is never met, so the caller (SYSTEM_ADDRESS) is not
tracked.
This condition is applied for the syscall in the geth implementation,
aligning with the spec of EIP7928.
---------
Co-authored-by: Felix Lange <fjl@twurst.com>
This PR adds OpenTelemetry tracing configuration to geth via
command-line flags. When enabled, geth initializes the global
OpenTelemetry TracerProvider and installs standard trace context
propagation. When disabled (the default), tracing remains a no-op and
behavior is unchanged.
Co-authored-by: Felix Lange <fjl@twurst.com>
This fixes two cases where `Iterator.Err()` was misused. The method will
only return an error after `Next()` has returned false, so it makes no
sense to check for the error within the loop itself.
This PR makes `TestEIP8024_Execution` verify explicit error types (e.g.,
`ErrStackUnderflow` vs `ErrInvalidOpCode`) rather than accepting any
error. It also fails fast on unexpected opcodes in the mini-interpreter
to avoid false positives from missing opcode handling.
Here is a draft for the New EraE implementation. The code follows along
with the spec listed at https://hackmd.io/pIZlxnitSciV5wUgW6W20w.
---------
Co-authored-by: shantichanal <158101918+shantichanal@users.noreply.github.com>
Co-authored-by: lightclient <lightclient@protonmail.com>
Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>