core/state, core/vm: emit burn logs at the end of state transition

This commit is contained in:
Gary Rong 2026-03-23 21:16:34 +08:00
parent c86093a934
commit 0a34ef1097
5 changed files with 22 additions and 12 deletions

View file

@ -748,18 +748,24 @@ type RemovedAccountWithBalance struct {
Balance *uint256.Int 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 // 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 // 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 // still receive funds between sending/burning its previous balance and actual
// removal. In this case the burning of these remaining balances still need to // removal. In this case the burning of these remaining balances still need to
// be logged. // be logged.
// Specification EIP-7708: https://eips.ethereum.org/EIPS/eip-7708 // 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 { for addr := range s.journal.dirties {
if obj, exist := s.stateObjects[addr]; exist && if obj, exist := s.stateObjects[addr]; exist && obj.selfDestructed && !obj.Balance().IsZero() {
obj.selfDestructed && !obj.Balance().IsZero() { list = append(list, RemovedAccountWithBalance{
list = append(list, RemovedAccountWithBalance{Address: obj.address, Balance: obj.Balance()}) Address: obj.address,
Balance: obj.Balance(),
})
} }
} }
if list != nil { if list != nil {
@ -767,7 +773,9 @@ func (s *StateDB) GetRemovedAccountsWithBalance() (list []RemovedAccountWithBala
return list[i].Address.Cmp(list[j].Address) < 0 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 // Finalise finalises the state by removing the destructed objects and clears

View file

@ -229,6 +229,10 @@ func (s *hookedStateDB) AddLog(log *types.Log) {
} }
} }
func (s *hookedStateDB) EmitLogsForBurnAccounts() {
s.inner.EmitLogsForBurnAccounts()
}
func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) { 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 { 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. // Short circuit if no relevant hooks are set.

View file

@ -173,12 +173,6 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB,
if err != nil { if err != nil {
return nil, err 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. // Update the state with pending changes.
var root []byte var root []byte
if evm.ChainConfig().IsByzantium(blockNumber) { if evm.ChainConfig().IsByzantium(blockNumber) {

View file

@ -583,6 +583,9 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
st.evm.AccessEvents.AddAccount(st.evm.Context.Coinbase, true, math.MaxUint64) 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{ return &ExecutionResult{
UsedGas: st.gasUsed(), UsedGas: st.gasUsed(),
MaxUsedGas: peakGasUsed, MaxUsedGas: peakGasUsed,

View file

@ -87,6 +87,7 @@ type StateDB interface {
Snapshot() int Snapshot() int
AddLog(*types.Log) AddLog(*types.Log)
EmitLogsForBurnAccounts()
AddPreimage(common.Hash, []byte) AddPreimage(common.Hash, []byte)
Witness() *stateless.Witness Witness() *stateless.Witness