diff --git a/core/state/statedb.go b/core/state/statedb.go index f85d877b34..940c60f27d 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -844,6 +844,21 @@ func (s *StateDB) GetRefund() uint64 { return s.refund } +type RemovedAccountWithBalance struct { + Address common.Address + Balance *uint256.Int +} + +func (s *StateDB) GetRemovedAccountsWithBalance() (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()}) + } + } + return list +} + // Finalise finalises the state by removing the destructed objects and clears // the journal as well as the refunds. Finalise, however, will not push any updates // into the tries just yet. Only IntermediateRoot or Commit will do that. diff --git a/core/state_processor.go b/core/state_processor.go index a7b55e0ff9..e5ddf2cbd2 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -19,6 +19,7 @@ package core import ( "fmt" "math/big" + "sort" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/misc" @@ -160,6 +161,18 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, if err != nil { return nil, err } + if evm.ChainConfig().IsAmsterdam(blockNumber, blockTime) { + // Emit Selfdesctruct logs where accounts with non-empty balances have been deleted + removedWithBalance := statedb.GetRemovedAccountsWithBalance() + if removedWithBalance != nil { + sort.Slice(removedWithBalance, func(i, j int) bool { + return removedWithBalance[i].Address.Cmp(removedWithBalance[j].Address) < 0 + }) + for _, sd := range removedWithBalance { + statedb.AddLog(types.EthSelfDestructLog(blockNumber, sd.Address, sd.Balance)) + } + } + } // Update the state with pending changes. var root []byte if evm.ChainConfig().IsByzantium(blockNumber) { diff --git a/core/types/log.go b/core/types/log.go index a6765fce21..3dd7fb1723 100644 --- a/core/types/log.go +++ b/core/types/log.go @@ -72,7 +72,7 @@ var ( // keccak256('Transfer(address,address,uint256)') EthTransferLogTopic0 = common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") // keccak256('Selfdestruct(address,uint256)') - EthBurnLogTopic0 = common.HexToHash("0x4bfaba3443c1a1836cd362418edc679fc96cae8449cbefccb6457cdf2c943083") + EthSelfDestructLogTopic0 = common.HexToHash("0x4bfaba3443c1a1836cd362418edc679fc96cae8449cbefccb6457cdf2c943083") ) // EthTransferLog creates and ETH transfer log according to EIP-7708. @@ -93,14 +93,14 @@ func EthTransferLog(blockNumber *big.Int, from, to common.Address, amount *uint2 } } -// EthBurnLog creates and ETH self-destruct burn log according to EIP-7708. +// EthSelfDestructLog creates and ETH self-destruct burn log according to EIP-7708. // Specification: https://eips.ethereum.org/EIPS/eip-7708 -func EthBurnLog(blockNumber *big.Int, from common.Address, amount *uint256.Int) *Log { +func EthSelfDestructLog(blockNumber *big.Int, from common.Address, amount *uint256.Int) *Log { amount32 := amount.Bytes32() return &Log{ Address: EthSystemLogAddress, Topics: []common.Hash{ - EthBurnLogTopic0, + EthSelfDestructLogTopic0, common.BytesToHash(from.Bytes()), }, Data: amount32[:], diff --git a/core/vm/instructions.go b/core/vm/instructions.go index b22864d045..26762b5b90 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -895,13 +895,6 @@ func opSelfdestruct(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { } // Clear any leftover funds for the account being destructed. evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct) - if evm.chainRules.IsAmsterdam && !balance.IsZero() { - if this != beneficiary { - evm.StateDB.AddLog(types.EthTransferLog(evm.Context.BlockNumber, this, beneficiary, balance)) - } else { - evm.StateDB.AddLog(types.EthBurnLog(evm.Context.BlockNumber, this, balance)) - } - } evm.StateDB.SelfDestruct(this) if tracer := evm.Config.Tracer; tracer != nil { @@ -944,7 +937,7 @@ func opSelfdestruct6780(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, erro if this != beneficiary { evm.StateDB.AddLog(types.EthTransferLog(evm.Context.BlockNumber, this, beneficiary, balance)) } else if newContract { - evm.StateDB.AddLog(types.EthBurnLog(evm.Context.BlockNumber, this, balance)) + evm.StateDB.AddLog(types.EthSelfDestructLog(evm.Context.BlockNumber, this, balance)) } }