From bde29cee4471d2efbe064caa7a23bcbe57e4a622 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Wed, 24 Jun 2026 17:36:01 +0200 Subject: [PATCH] 2780: don't charge for precompiles --- core/state_transition.go | 5 ++++- core/vm/evm.go | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/core/state_transition.go b/core/state_transition.go index 22ccd53542..7a901cf707 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -854,7 +854,10 @@ func (st *stateTransition) chargeCallRecipientEIP2780(value *uint256.Int) bool { cost vm.GasCosts to = *st.msg.To ) - if !value.IsZero() && st.state.Empty(to) { + // EIP-8037: a value transfer to an empty recipient charges NEW_ACCOUNT + // state gas — except for precompiles, which are protocol-inherent and not + // "created" by the transfer, so the charge is suppressed for them. + if !value.IsZero() && st.state.Empty(to) && !st.evm.IsPrecompile(to) { cost.StateGas += params.AccountCreationSize * st.evm.Context.CostPerStateByte } if _, ok := types.ParseDelegation(st.state.GetCode(to)); ok { diff --git a/core/vm/evm.go b/core/vm/evm.go index c86704c54c..f542ff6eac 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -46,6 +46,13 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { return p, ok } +// IsPrecompile reports whether addr is an active precompile for the current +// fork ruleset. +func (evm *EVM) IsPrecompile(addr common.Address) bool { + _, ok := evm.precompiles[addr] + return ok +} + // BlockContext provides the EVM with auxiliary information. Once provided // it shouldn't be modified. type BlockContext struct {