diff --git a/core/state/statedb.go b/core/state/statedb.go index e3ed0bbaec..956b89f2cc 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -748,18 +748,24 @@ type RemovedAccountWithBalance struct { Balance *uint256.Int } -// GetRemovedAccountsWithBalance returns a list of accounts scheduled for +// EmitLogsForBurnAccounts emits the eth transfer logs for accounts scheduled for // removal which still have positive balance. The purpose of this function is // to handle a corner case of EIP-7708 where a self-destructed account might // still receive funds between sending/burning its previous balance and actual // removal. In this case the burning of these remaining balances still need to // be logged. // Specification EIP-7708: https://eips.ethereum.org/EIPS/eip-7708 -func (s *StateDB) GetRemovedAccountsWithBalance() (list []RemovedAccountWithBalance) { +// +// This function should only be invoked at the transaction boundary, specifically +// before the Finalise. +func (s *StateDB) EmitLogsForBurnAccounts() { + var list []RemovedAccountWithBalance for addr := range s.journal.dirties { - if obj, exist := s.stateObjects[addr]; exist && - obj.selfDestructed && !obj.Balance().IsZero() { - list = append(list, RemovedAccountWithBalance{Address: obj.address, Balance: obj.Balance()}) + if obj, exist := s.stateObjects[addr]; exist && obj.selfDestructed && !obj.Balance().IsZero() { + list = append(list, RemovedAccountWithBalance{ + Address: obj.address, + Balance: obj.Balance(), + }) } } if list != nil { @@ -767,7 +773,9 @@ func (s *StateDB) GetRemovedAccountsWithBalance() (list []RemovedAccountWithBala return list[i].Address.Cmp(list[j].Address) < 0 }) } - return list + for _, acct := range list { + s.AddLog(types.EthBurnLog(acct.Address, acct.Balance)) + } } // Finalise finalises the state by removing the destructed objects and clears diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go index 48794a3f41..8c217fba48 100644 --- a/core/state/statedb_hooked.go +++ b/core/state/statedb_hooked.go @@ -229,6 +229,10 @@ func (s *hookedStateDB) AddLog(log *types.Log) { } } +func (s *hookedStateDB) EmitLogsForBurnAccounts() { + s.inner.EmitLogsForBurnAccounts() +} + func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) { if s.hooks.OnBalanceChange == nil && s.hooks.OnNonceChangeV2 == nil && s.hooks.OnNonceChange == nil && s.hooks.OnCodeChangeV2 == nil && s.hooks.OnCodeChange == nil { // Short circuit if no relevant hooks are set. diff --git a/core/state_processor.go b/core/state_processor.go index 80f1b6818b..85f106d58c 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -173,12 +173,6 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, if err != nil { return nil, err } - if evm.ChainConfig().IsAmsterdam(blockNumber, blockTime) { - // Emit burn logs where accounts with non-empty balances have been deleted - for _, sd := range statedb.GetRemovedAccountsWithBalance() { - statedb.AddLog(types.EthBurnLog(sd.Address, sd.Balance)) - } - } // Update the state with pending changes. var root []byte if evm.ChainConfig().IsByzantium(blockNumber) { diff --git a/core/state_transition.go b/core/state_transition.go index 6a40b4f7ab..bcbbaba6ca 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -583,6 +583,9 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { st.evm.AccessEvents.AddAccount(st.evm.Context.Coinbase, true, math.MaxUint64) } } + if st.evm.ChainConfig().IsAmsterdam(st.evm.Context.BlockNumber, st.evm.Context.Time) { + st.evm.StateDB.EmitLogsForBurnAccounts() + } return &ExecutionResult{ UsedGas: st.gasUsed(), MaxUsedGas: peakGasUsed, diff --git a/core/vm/interface.go b/core/vm/interface.go index e285b18b0f..6a93846ac5 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -87,6 +87,7 @@ type StateDB interface { Snapshot() int AddLog(*types.Log) + EmitLogsForBurnAccounts() AddPreimage(common.Hash, []byte) Witness() *stateless.Witness