From cb3122b280f98e2260ca7f4e0b194bae1cb5a440 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Tue, 27 Jan 2026 22:57:28 +0100 Subject: [PATCH] core/state: move code write metrics to post-Finalise Count CodeUpdated and CodeBytesWrite in IntermediateRoot() instead of SetCode(), consistent with how AccountUpdated, StorageUpdated, and StorageDeleted are already measured. This ensures reverted CREATEs from failed inner call frames are not counted. EIP-7702 delegation counters remain in SetCode() as authorizations are applied at the transaction level (applyAuthorization), outside revertable EVM call frames. --- core/state/statedb.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index 044778ad38..56087f75ed 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -171,8 +171,8 @@ type StateDB struct { Eip7702DelegationsCleared int // Number of EIP-7702 delegations cleared // Code write tracking for cross-client execution metrics - CodeUpdated int // Number of contracts deployed (CREATE/CREATE2) - CodeBytesWrite int // Total bytes of code written during deployments + CodeUpdated int // Number of contracts with code changes that persisted + CodeBytesWrite int // Total bytes of persisted code written } // New creates a new state from a given trie. @@ -481,14 +481,10 @@ func (s *StateDB) SetNonce(addr common.Address, nonce uint64, reason tracing.Non func (s *StateDB) SetCode(addr common.Address, code []byte, reason tracing.CodeChangeReason) (prev []byte) { stateObject := s.getOrNewStateObject(addr) if stateObject != nil { - // Track code write and EIP-7702 delegation metrics + // EIP-7702 delegation counters are safe here: authorizations are applied + // at transaction level (applyAuthorization), outside revertable EVM frames. switch reason { - case tracing.CodeChangeContractCreation: - s.CodeUpdated++ - s.CodeBytesWrite += len(code) case tracing.CodeChangeAuthorization: - s.CodeUpdated++ - s.CodeBytesWrite += len(code) s.Eip7702DelegationsSet++ case tracing.CodeChangeAuthorizationClear: s.Eip7702DelegationsCleared++ @@ -961,8 +957,15 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { if op.isDelete() { deletedAddrs = append(deletedAddrs, addr) } else { - s.updateStateObject(s.stateObjects[addr]) + obj := s.stateObjects[addr] + s.updateStateObject(obj) s.AccountUpdated += 1 + // Count code writes post-Finalise so reverted CREATEs are excluded. + // Only count non-empty code (clears like EIP-7702 revocations are not code writes). + if obj.dirtyCode && len(obj.code) > 0 { + s.CodeUpdated += 1 + s.CodeBytesWrite += len(obj.code) + } } usedAddrs = append(usedAddrs, addr) // Copy needed for closure }