From 1c442e5edc926de0a4727fa39d1ebb7cbccabc87 Mon Sep 17 00:00:00 2001 From: yperbasis Date: Thu, 22 Jan 2026 14:59:42 +0100 Subject: [PATCH 1/3] mv SystemAddress to params --- execution/protocol/block_exec.go | 5 +++-- execution/protocol/params/protocol.go | 22 +++++++++++++-------- execution/protocol/state_transition.go | 2 +- execution/stagedsync/bal_create.go | 3 ++- execution/state/intra_block_state.go | 6 ++---- polygon/bridge/reader.go | 10 +++++----- polygon/tracer/bor_state_sync_txn_tracer.go | 4 ++-- 7 files changed, 29 insertions(+), 23 deletions(-) diff --git a/execution/protocol/block_exec.go b/execution/protocol/block_exec.go index 87db8893973..89d76817c28 100644 --- a/execution/protocol/block_exec.go +++ b/execution/protocol/block_exec.go @@ -36,6 +36,7 @@ import ( "github.com/erigontech/erigon/common/u256" "github.com/erigontech/erigon/diagnostics/metrics" "github.com/erigontech/erigon/execution/chain" + "github.com/erigontech/erigon/execution/protocol/params" "github.com/erigontech/erigon/execution/protocol/rules" "github.com/erigontech/erigon/execution/rlp" "github.com/erigontech/erigon/execution/state" @@ -267,7 +268,7 @@ func SysCallContract(contract accounts.Address, data []byte, chainConfig *chain. if isBor { author = accounts.InternAddress(header.Coinbase) } else { - author = state.SystemAddress + author = params.SystemAddress } blockContext := NewEVMBlockContext(header, GetHashFn(header, nil), engine, author, chainConfig) return SysCallContractWithBlockContext(contract, data, chainConfig, ibs, blockContext, constCall, vmCfg) @@ -276,7 +277,7 @@ func SysCallContract(contract accounts.Address, data []byte, chainConfig *chain. func SysCallContractWithBlockContext(contract accounts.Address, data []byte, chainConfig *chain.Config, ibs *state.IntraBlockState, blockContext evmtypes.BlockContext, constCall bool, vmCfg vm.Config) (result []byte, err error) { isBor := chainConfig.Bor != nil msg := types.NewMessage( - state.SystemAddress, + params.SystemAddress, contract, 0, &u256.Num0, SysCallGasLimit, diff --git a/execution/protocol/params/protocol.go b/execution/protocol/params/protocol.go index 6fb82d74439..7c930ca0c9b 100644 --- a/execution/protocol/params/protocol.go +++ b/execution/protocol/params/protocol.go @@ -214,17 +214,23 @@ const ( var DelegatedDesignationPrefix = []byte{0xef, 0x01, 0x00} var DelegatedCodeHash = common.HexToHash("0xeadcdba66a79ab5dce91622d1d75c8cff5cff0b96944c3bf1072cd08ce018329") -// EIP-4788: Beacon block root in the EVM -var BeaconRootsAddress = accounts.InternAddress(common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")) +// System contracts +var ( + // SystemAddress is where the system-transaction is sent from as per EIP-4788 + SystemAddress = accounts.InternAddress(common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")) + + // EIP-4788: Beacon block root in the EVM + BeaconRootsAddress = accounts.InternAddress(common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")) -// EIP-2935: Historical block hashes in state -var HistoryStorageAddress = accounts.InternAddress(common.HexToAddress("0x0000F90827F1C53a10cb7A02335B175320002935")) + // EIP-2935: Historical block hashes in state + HistoryStorageAddress = accounts.InternAddress(common.HexToAddress("0x0000F90827F1C53a10cb7A02335B175320002935")) -// EIP-7002: Execution layer triggerable withdrawals -var WithdrawalRequestAddress = accounts.InternAddress(common.HexToAddress("0x00000961Ef480Eb55e80D19ad83579A64c007002")) + // EIP-7002: Execution layer triggerable withdrawals + WithdrawalRequestAddress = accounts.InternAddress(common.HexToAddress("0x00000961Ef480Eb55e80D19ad83579A64c007002")) -// EIP-7251 -var ConsolidationRequestAddress = accounts.InternAddress(common.HexToAddress("0x0000BBdDc7CE488642fb579F8B00f3a590007251")) + // EIP-7251: Increase the MAX_EFFECTIVE_BALANCE + ConsolidationRequestAddress = accounts.InternAddress(common.HexToAddress("0x0000BBdDc7CE488642fb579F8B00f3a590007251")) +) // Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations var Bls12381MSMDiscountTableG1 = [128]uint64{1000, 949, 848, 797, 764, 750, 738, 728, 719, 712, 705, 698, 692, 687, 682, 677, 673, 669, 665, 661, 658, 654, 651, 648, 645, 642, 640, 637, 635, 632, 630, 627, 625, 623, 621, 619, 617, 615, 613, 611, 609, 608, 606, 604, 603, 601, 599, 598, 596, 595, 593, 592, 591, 589, 588, 586, 585, 584, 582, 581, 580, 579, 577, 576, 575, 574, 573, 572, 570, 569, 568, 567, 566, 565, 564, 563, 562, 561, 560, 559, 558, 557, 556, 555, 554, 553, 552, 551, 550, 549, 548, 547, 547, 546, 545, 544, 543, 542, 541, 540, 540, 539, 538, 537, 536, 536, 535, 534, 533, 532, 532, 531, 530, 529, 528, 528, 527, 526, 525, 525, 524, 523, 522, 522, 521, 520, 520, 519} diff --git a/execution/protocol/state_transition.go b/execution/protocol/state_transition.go index 6ede6c25517..876591359c5 100644 --- a/execution/protocol/state_transition.go +++ b/execution/protocol/state_transition.go @@ -159,7 +159,7 @@ func applyMessage(evm *vm.EVM, msg Message, gp *GasPool, refunds bool, gasBailou // Only zero-gas transactions may be service ones if msg.FeeCap().IsZero() && !msg.IsFree() && engine != nil { blockContext := evm.Context - blockContext.Coinbase = state.SystemAddress + blockContext.Coinbase = params.SystemAddress syscall := func(contract accounts.Address, data []byte) ([]byte, error) { ret, err := SysCallContractWithBlockContext(contract, data, evm.ChainConfig(), evm.IntraBlockState(), blockContext, true, evm.Config()) return ret, err diff --git a/execution/stagedsync/bal_create.go b/execution/stagedsync/bal_create.go index b0131c29404..45476fffcc1 100644 --- a/execution/stagedsync/bal_create.go +++ b/execution/stagedsync/bal_create.go @@ -12,6 +12,7 @@ import ( "github.com/erigontech/erigon/common" "github.com/erigontech/erigon/common/log/v3" + "github.com/erigontech/erigon/execution/protocol/params" "github.com/erigontech/erigon/execution/state" "github.com/erigontech/erigon/execution/types" "github.com/erigontech/erigon/execution/types/accounts" @@ -169,7 +170,7 @@ func updateAccountWrite(account *accountState, vw *state.VersionedWrite, accessI } func isSystemBALAddress(addr accounts.Address) bool { - return addr == state.SystemAddress + return addr == params.SystemAddress } func hasStorageWrite(ac *types.AccountChanges, slot accounts.StorageKey) bool { diff --git a/execution/state/intra_block_state.go b/execution/state/intra_block_state.go index ff1a3d92eb7..09cc8ea60dd 100644 --- a/execution/state/intra_block_state.go +++ b/execution/state/intra_block_state.go @@ -37,6 +37,7 @@ import ( "github.com/erigontech/erigon/common/u256" "github.com/erigontech/erigon/execution/chain" "github.com/erigontech/erigon/execution/commitment/trie" + "github.com/erigontech/erigon/execution/protocol/params" "github.com/erigontech/erigon/execution/tracing" "github.com/erigontech/erigon/execution/types" "github.com/erigontech/erigon/execution/types/accounts" @@ -117,9 +118,6 @@ var revisionsPool = sync.Pool{ }, } -// SystemAddress - sender address for internal state updates. -var SystemAddress = accounts.InternAddress(common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")) - // BalanceIncrease represents the increase of balance of an account that did not require // reading the account first type BalanceIncrease struct { @@ -1516,7 +1514,7 @@ func (sdb *IntraBlockState) GetRefund() uint64 { } func updateAccount(EIP161Enabled bool, isAura bool, stateWriter StateWriter, addr accounts.Address, stateObject *stateObject, isDirty bool, trace bool, tracingHooks *tracing.Hooks) error { - emptyRemoval := EIP161Enabled && stateObject.data.Empty() && (!isAura || addr != SystemAddress) + emptyRemoval := EIP161Enabled && stateObject.data.Empty() && (!isAura || addr != params.SystemAddress) if stateObject.selfdestructed || (isDirty && emptyRemoval) { balance := stateObject.Balance() if tracingHooks != nil && tracingHooks.OnBalanceChange != nil && !(&balance).IsZero() && stateObject.selfdestructed { diff --git a/polygon/bridge/reader.go b/polygon/bridge/reader.go index 078b1243eea..51db4d5722d 100644 --- a/polygon/bridge/reader.go +++ b/polygon/bridge/reader.go @@ -29,8 +29,8 @@ import ( "github.com/erigontech/erigon/common/log/v3" "github.com/erigontech/erigon/common/u256" "github.com/erigontech/erigon/execution/protocol" + "github.com/erigontech/erigon/execution/protocol/params" "github.com/erigontech/erigon/execution/rlp" - "github.com/erigontech/erigon/execution/state" "github.com/erigontech/erigon/execution/types" "github.com/erigontech/erigon/execution/types/accounts" "github.com/erigontech/erigon/node/gointerfaces" @@ -95,7 +95,7 @@ func (r *Reader) EventsWithinTime(ctx context.Context, timeFrom, timeTo time.Tim // convert to message for _, event := range events { msg := types.NewMessage( - state.SystemAddress, + params.SystemAddress, r.stateClientAddress, 0, &u256.Num0, protocol.SysCallGasLimit, @@ -131,7 +131,7 @@ func (r *Reader) Events(ctx context.Context, blockHash common.Hash, blockNum uin // convert to message for _, event := range events { msg := types.NewMessage( - state.SystemAddress, + params.SystemAddress, r.stateClientAddress, 0, &u256.Num0, protocol.SysCallGasLimit, @@ -227,7 +227,7 @@ func (r *RemoteReader) EnsureVersionCompatibility() bool { func messageFromData(to accounts.Address, data []byte) *types.Message { msg := types.NewMessage( - state.SystemAddress, + params.SystemAddress, to, 0, &u256.Num0, protocol.SysCallGasLimit, @@ -249,7 +249,7 @@ func NewStateSyncEventMessages(stateSyncEvents []rlp.RawValue, stateReceiverCont msgs := make([]*types.Message, len(stateSyncEvents)) for i, event := range stateSyncEvents { msg := types.NewMessage( - state.SystemAddress, // from + params.SystemAddress, // from stateReceiverContract, 0, // nonce &u256.Num0, // amount diff --git a/polygon/tracer/bor_state_sync_txn_tracer.go b/polygon/tracer/bor_state_sync_txn_tracer.go index c949242ce3b..98ddc6817ab 100644 --- a/polygon/tracer/bor_state_sync_txn_tracer.go +++ b/polygon/tracer/bor_state_sync_txn_tracer.go @@ -22,7 +22,7 @@ import ( "github.com/holiman/uint256" "github.com/erigontech/erigon/common/u256" - "github.com/erigontech/erigon/execution/state" + "github.com/erigontech/erigon/execution/protocol/params" "github.com/erigontech/erigon/execution/tracing" "github.com/erigontech/erigon/execution/tracing/tracers" "github.com/erigontech/erigon/execution/types" @@ -99,7 +99,7 @@ func (bsstt *borStateSyncTxnTracer) OnExit(depth int, output []byte, gasUsed uin func (bsstt *borStateSyncTxnTracer) OnEnter(depth int, typ byte, from accounts.Address, to accounts.Address, precompile bool, input []byte, gas uint64, value uint256.Int, code []byte) { if bsstt.Tracer.OnEnter != nil { if !bsstt.createdTopLevel { - bsstt.Tracer.OnEnter(0, byte(vm.CALL), state.SystemAddress, bsstt.stateReceiverContractAddress, false, nil, 0, u256.N0, nil) + bsstt.Tracer.OnEnter(0, byte(vm.CALL), params.SystemAddress, bsstt.stateReceiverContractAddress, false, nil, 0, u256.N0, nil) bsstt.createdTopLevel = true } From 60f67f30aeaaf41db4e11e33df68cf00774a0b1c Mon Sep 17 00:00:00 2001 From: Zsolt Felfoldi Date: Mon, 19 Jan 2026 18:51:09 +0100 Subject: [PATCH 2/3] core, core/vm: implement EIP-7708 --- execution/protocol/evm.go | 2 +- execution/protocol/misc/eip7708.go | 79 +++++++++++++++++++ execution/protocol/params/protocol.go | 7 ++ execution/protocol/rules/aura/aura.go | 3 +- execution/protocol/rules/clique/clique.go | 3 +- execution/protocol/rules/ethash/ethash.go | 3 +- execution/protocol/rules/rules.go | 13 +-- execution/state/intra_block_state.go | 10 +-- .../internal/tracetest/calltrace_test.go | 8 +- .../internal/tracetest/prestate_test.go | 4 +- execution/tracing/tracers/tracers_test.go | 4 +- execution/vm/evm.go | 4 +- execution/vm/evmtypes/evmtypes.go | 3 +- execution/vm/gas_table_test.go | 4 +- execution/vm/instructions.go | 13 ++- execution/vm/runtime/env.go | 4 +- polygon/bor/bor.go | 4 +- rpc/jsonrpc/trace_adhoc_test.go | 4 +- 18 files changed, 131 insertions(+), 41 deletions(-) create mode 100644 execution/protocol/misc/eip7708.go diff --git a/execution/protocol/evm.go b/execution/protocol/evm.go index a3ab942e7c1..a844218a2bf 100644 --- a/execution/protocol/evm.go +++ b/execution/protocol/evm.go @@ -87,7 +87,7 @@ func NewEVMBlockContext(header *types.Header, blockHashFunc func(n uint64) (comm transferFunc = engine.GetTransferFunc() postApplyMessageFunc = engine.GetPostApplyMessageFunc() } else { - transferFunc = rules.Transfer + transferFunc = misc.Transfer postApplyMessageFunc = nil } blockContext := evmtypes.BlockContext{ diff --git a/execution/protocol/misc/eip7708.go b/execution/protocol/misc/eip7708.go new file mode 100644 index 00000000000..ec6b093836b --- /dev/null +++ b/execution/protocol/misc/eip7708.go @@ -0,0 +1,79 @@ +// Copyright 2026 The go-ethereum Authors +// (original work) +// Copyright 2026 The Erigon Authors +// (modifications) +// This file is part of Erigon. +// +// Erigon is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Erigon is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Erigon. If not, see . + +package misc + +import ( + "github.com/holiman/uint256" + + "github.com/erigontech/erigon/common" + "github.com/erigontech/erigon/execution/chain" + "github.com/erigontech/erigon/execution/protocol/params" + "github.com/erigontech/erigon/execution/tracing" + "github.com/erigontech/erigon/execution/types" + "github.com/erigontech/erigon/execution/types/accounts" + "github.com/erigontech/erigon/execution/vm/evmtypes" +) + +// EthTransferLog creates and ETH transfer log according to EIP-7708. +// Specification: https://eips.ethereum.org/EIPS/eip-7708 +func EthTransferLog(from, to accounts.Address, amount uint256.Int) *types.Log { + amount32 := amount.Bytes32() + return &types.Log{ + Address: params.SystemAddress.Value(), + Topics: []common.Hash{ + params.EthTransferLogEvent, + from.Value().Hash(), + to.Value().Hash(), + }, + Data: amount32[:], + } +} + +// EthSelfDestructLog creates and ETH self-destruct burn log according to EIP-7708. +// Specification: https://eips.ethereum.org/EIPS/eip-7708 +func EthSelfDestructLog(from accounts.Address, amount uint256.Int) *types.Log { + amount32 := amount.Bytes32() + return &types.Log{ + Address: params.SystemAddress.Value(), + Topics: []common.Hash{ + params.EthSelfDestructLogEvent, + from.Value().Hash(), + }, + Data: amount32[:], + } +} + +// Transfer subtracts amount from sender and adds amount to recipient using the given Db +func Transfer(db evmtypes.IntraBlockState, sender, recipient accounts.Address, amount uint256.Int, bailout bool, rules *chain.Rules) error { + if !bailout { + err := db.SubBalance(sender, amount, tracing.BalanceChangeTransfer) + if err != nil { + return err + } + } + err := db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer) + if err != nil { + return err + } + if rules.IsAmsterdam && !amount.IsZero() { + db.AddLog(EthTransferLog(sender, recipient, amount)) + } + return nil +} diff --git a/execution/protocol/params/protocol.go b/execution/protocol/params/protocol.go index 7c930ca0c9b..5da6e51c916 100644 --- a/execution/protocol/params/protocol.go +++ b/execution/protocol/params/protocol.go @@ -232,6 +232,13 @@ var ( ConsolidationRequestAddress = accounts.InternAddress(common.HexToAddress("0x0000BBdDc7CE488642fb579F8B00f3a590007251")) ) +// System log events +var ( + // EIP-7708 - System logs emitted for ETH transfer and self-destruct balance burn + EthTransferLogEvent = common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") // keccak256('Transfer(address,address,uint256)') + EthSelfDestructLogEvent = common.HexToHash("0x4bfaba3443c1a1836cd362418edc679fc96cae8449cbefccb6457cdf2c943083") // keccak256('Selfdestruct(address,uint256)') +) + // Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations var Bls12381MSMDiscountTableG1 = [128]uint64{1000, 949, 848, 797, 764, 750, 738, 728, 719, 712, 705, 698, 692, 687, 682, 677, 673, 669, 665, 661, 658, 654, 651, 648, 645, 642, 640, 637, 635, 632, 630, 627, 625, 623, 621, 619, 617, 615, 613, 611, 609, 608, 606, 604, 603, 601, 599, 598, 596, 595, 593, 592, 591, 589, 588, 586, 585, 584, 582, 581, 580, 579, 577, 576, 575, 574, 573, 572, 570, 569, 568, 567, 566, 565, 564, 563, 562, 561, 560, 559, 558, 557, 556, 555, 554, 553, 552, 551, 550, 549, 548, 547, 547, 546, 545, 544, 543, 542, 541, 540, 540, 539, 538, 537, 536, 536, 535, 534, 533, 532, 532, 531, 530, 529, 528, 528, 527, 526, 525, 525, 524, 523, 522, 522, 521, 520, 520, 519} diff --git a/execution/protocol/rules/aura/aura.go b/execution/protocol/rules/aura/aura.go index d1fa0339ead..81eab56004d 100644 --- a/execution/protocol/rules/aura/aura.go +++ b/execution/protocol/rules/aura/aura.go @@ -31,6 +31,7 @@ import ( "github.com/erigontech/erigon/common/log/v3" "github.com/erigontech/erigon/db/kv" "github.com/erigontech/erigon/execution/chain" + "github.com/erigontech/erigon/execution/protocol/misc" "github.com/erigontech/erigon/execution/protocol/rules" "github.com/erigontech/erigon/execution/protocol/rules/clique" "github.com/erigontech/erigon/execution/protocol/rules/ethash" @@ -1162,7 +1163,7 @@ func (c *AuRa) ExecuteSystemWithdrawals(withdrawals []*types.Withdrawal, syscall } func (c *AuRa) GetTransferFunc() evmtypes.TransferFunc { - return rules.Transfer + return misc.Transfer } func (c *AuRa) GetPostApplyMessageFunc() evmtypes.PostApplyMessageFunc { diff --git a/execution/protocol/rules/clique/clique.go b/execution/protocol/rules/clique/clique.go index be27da137c6..0b39553415e 100644 --- a/execution/protocol/rules/clique/clique.go +++ b/execution/protocol/rules/clique/clique.go @@ -44,6 +44,7 @@ import ( "github.com/erigontech/erigon/db/services" "github.com/erigontech/erigon/execution/chain" chainspec "github.com/erigontech/erigon/execution/chain/spec" + "github.com/erigontech/erigon/execution/protocol/misc" "github.com/erigontech/erigon/execution/protocol/rules" "github.com/erigontech/erigon/execution/rlp" "github.com/erigontech/erigon/execution/state" @@ -641,7 +642,7 @@ func (c *Clique) snapshots(latest uint64, total int) ([]*Snapshot, error) { } func (c *Clique) GetTransferFunc() evmtypes.TransferFunc { - return rules.Transfer + return misc.Transfer } func (c *Clique) GetPostApplyMessageFunc() evmtypes.PostApplyMessageFunc { diff --git a/execution/protocol/rules/ethash/ethash.go b/execution/protocol/rules/ethash/ethash.go index 34c5d0477a4..f4317fc5647 100644 --- a/execution/protocol/rules/ethash/ethash.go +++ b/execution/protocol/rules/ethash/ethash.go @@ -41,6 +41,7 @@ import ( dir2 "github.com/erigontech/erigon/common/dir" "github.com/erigontech/erigon/common/log/v3" "github.com/erigontech/erigon/common/math" + "github.com/erigontech/erigon/execution/protocol/misc" "github.com/erigontech/erigon/execution/protocol/rules" "github.com/erigontech/erigon/execution/protocol/rules/ethash/ethashcfg" "github.com/erigontech/erigon/execution/types" @@ -580,7 +581,7 @@ func SeedHash(block uint64) []byte { } func (ethash *Ethash) GetTransferFunc() evmtypes.TransferFunc { - return rules.Transfer + return misc.Transfer } func (ethash *Ethash) GetPostApplyMessageFunc() evmtypes.PostApplyMessageFunc { diff --git a/execution/protocol/rules/rules.go b/execution/protocol/rules/rules.go index e5c88ac2734..746039ffc28 100644 --- a/execution/protocol/rules/rules.go +++ b/execution/protocol/rules/rules.go @@ -25,7 +25,7 @@ import ( "github.com/holiman/uint256" - common "github.com/erigontech/erigon/common" + "github.com/erigontech/erigon/common" "github.com/erigontech/erigon/common/log/v3" "github.com/erigontech/erigon/execution/chain" "github.com/erigontech/erigon/execution/state" @@ -200,14 +200,3 @@ type PoW interface { // Hashrate returns the current mining hashrate of a PoW rules engine. Hashrate() float64 } - -// Transfer subtracts amount from sender and adds amount to recipient using the given Db -func Transfer(db evmtypes.IntraBlockState, sender, recipient accounts.Address, amount uint256.Int, bailout bool) error { - if !bailout { - err := db.SubBalance(sender, amount, tracing.BalanceChangeTransfer) - if err != nil { - return err - } - } - return db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer) -} diff --git a/execution/state/intra_block_state.go b/execution/state/intra_block_state.go index 09cc8ea60dd..821b4b24b0a 100644 --- a/execution/state/intra_block_state.go +++ b/execution/state/intra_block_state.go @@ -1184,24 +1184,24 @@ func (sdb *IntraBlockState) Selfdestruct(addr accounts.Address) (bool, error) { var zeroBalance uint256.Int -func (sdb *IntraBlockState) Selfdestruct6780(addr accounts.Address) error { +func (sdb *IntraBlockState) Selfdestruct6780(addr accounts.Address) (newlyCreated bool, err error) { stateObject, err := sdb.getStateObject(addr) if err != nil { - return err + return false, err } if stateObject == nil { - return nil + return false, nil } if stateObject.newlyCreated { code, err := sdb.GetCode(addr) if err != nil { - return err + return false, err } if _, ok := types.ParseDelegation(code); !ok { sdb.Selfdestruct(addr) } } - return nil + return stateObject.newlyCreated, nil } // SetTransientState sets transient storage for a given account. It diff --git a/execution/tracing/tracers/internal/tracetest/calltrace_test.go b/execution/tracing/tracers/internal/tracetest/calltrace_test.go index 41aca310ab7..243afb7d0dc 100644 --- a/execution/tracing/tracers/internal/tracetest/calltrace_test.go +++ b/execution/tracing/tracers/internal/tracetest/calltrace_test.go @@ -38,7 +38,7 @@ import ( chainspec "github.com/erigontech/erigon/execution/chain/spec" "github.com/erigontech/erigon/execution/protocol" - consensus "github.com/erigontech/erigon/execution/protocol/rules" + "github.com/erigontech/erigon/execution/protocol/misc" "github.com/erigontech/erigon/execution/tests/mock" "github.com/erigontech/erigon/execution/tests/testutil" "github.com/erigontech/erigon/execution/tracing/tracers" @@ -139,7 +139,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { signer := types.MakeSigner(test.Genesis.Config, uint64(test.Context.Number), uint64(test.Context.Time)) context := evmtypes.BlockContext{ CanTransfer: protocol.CanTransfer, - Transfer: consensus.Transfer, + Transfer: misc.Transfer, Coinbase: accounts.InternAddress(test.Context.Miner), BlockNumber: uint64(test.Context.Number), Time: uint64(test.Context.Time), @@ -246,7 +246,7 @@ func benchTracer(b *testing.B, tracerName string, test *callTracerTest) { signer := types.MakeSigner(test.Genesis.Config, uint64(test.Context.Number), uint64(test.Context.Time)) context := evmtypes.BlockContext{ CanTransfer: protocol.CanTransfer, - Transfer: consensus.Transfer, + Transfer: misc.Transfer, Coinbase: accounts.InternAddress(test.Context.Miner), BlockNumber: uint64(test.Context.Number), Time: uint64(test.Context.Time), @@ -318,7 +318,7 @@ func TestZeroValueToNotExitCall(t *testing.T) { } context := evmtypes.BlockContext{ CanTransfer: protocol.CanTransfer, - Transfer: consensus.Transfer, + Transfer: misc.Transfer, Coinbase: accounts.ZeroAddress, BlockNumber: 8000000, Time: 5, diff --git a/execution/tracing/tracers/internal/tracetest/prestate_test.go b/execution/tracing/tracers/internal/tracetest/prestate_test.go index f34f52b676c..bc60298fab4 100644 --- a/execution/tracing/tracers/internal/tracetest/prestate_test.go +++ b/execution/tracing/tracers/internal/tracetest/prestate_test.go @@ -33,7 +33,7 @@ import ( "github.com/erigontech/erigon/common" "github.com/erigontech/erigon/common/dir" "github.com/erigontech/erigon/execution/protocol" - "github.com/erigontech/erigon/execution/protocol/rules" + "github.com/erigontech/erigon/execution/protocol/misc" "github.com/erigontech/erigon/execution/tests/mock" "github.com/erigontech/erigon/execution/tests/testutil" "github.com/erigontech/erigon/execution/tracing/tracers" @@ -105,7 +105,7 @@ func testPrestateTracer(tracerName string, dirPath string, t *testing.T) { signer := types.MakeSigner(test.Genesis.Config, uint64(test.Context.Number), uint64(test.Context.Time)) context := evmtypes.BlockContext{ CanTransfer: protocol.CanTransfer, - Transfer: rules.Transfer, + Transfer: misc.Transfer, Coinbase: accounts.InternAddress(test.Context.Miner), BlockNumber: uint64(test.Context.Number), Time: uint64(test.Context.Time), diff --git a/execution/tracing/tracers/tracers_test.go b/execution/tracing/tracers/tracers_test.go index 3609aee1ba6..e7103fb1fe2 100644 --- a/execution/tracing/tracers/tracers_test.go +++ b/execution/tracing/tracers/tracers_test.go @@ -34,7 +34,7 @@ import ( "github.com/erigontech/erigon/common/hexutil" "github.com/erigontech/erigon/execution/chain" "github.com/erigontech/erigon/execution/protocol" - "github.com/erigontech/erigon/execution/protocol/rules" + "github.com/erigontech/erigon/execution/protocol/misc" "github.com/erigontech/erigon/execution/tests/mock" "github.com/erigontech/erigon/execution/tests/testutil" "github.com/erigontech/erigon/execution/tracing/tracers" @@ -77,7 +77,7 @@ func TestPrestateTracerCreate2(t *testing.T) { } context := evmtypes.BlockContext{ CanTransfer: protocol.CanTransfer, - Transfer: rules.Transfer, + Transfer: misc.Transfer, Coinbase: accounts.ZeroAddress, BlockNumber: 8000000, Time: 5, diff --git a/execution/vm/evm.go b/execution/vm/evm.go index 7cf478c2c03..8298af66037 100644 --- a/execution/vm/evm.go +++ b/execution/vm/evm.go @@ -229,7 +229,7 @@ func (evm *EVM) call(typ OpCode, caller accounts.Address, callerAddress accounts } evm.intraBlockState.CreateAccount(addr, false) } - evm.Context.Transfer(evm.intraBlockState, caller, addr, value, bailout) + evm.Context.Transfer(evm.intraBlockState, caller, addr, value, bailout, evm.chainRules) } else if typ == STATICCALL { // We do an AddBalance of zero here, just in order to trigger a touch. // This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium, @@ -442,7 +442,7 @@ func (evm *EVM) create(caller accounts.Address, codeAndHash *codeAndHash, gasRem if evm.chainRules.IsSpuriousDragon { evm.intraBlockState.SetNonce(address, 1) } - evm.Context.Transfer(evm.intraBlockState, caller, address, value, bailout) + evm.Context.Transfer(evm.intraBlockState, caller, address, value, bailout, evm.chainRules) // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. diff --git a/execution/vm/evmtypes/evmtypes.go b/execution/vm/evmtypes/evmtypes.go index 6052eb7c9ed..c1cf4b85b07 100644 --- a/execution/vm/evmtypes/evmtypes.go +++ b/execution/vm/evmtypes/evmtypes.go @@ -22,6 +22,7 @@ import ( "github.com/holiman/uint256" "github.com/erigontech/erigon/common" + "github.com/erigontech/erigon/execution/chain" "github.com/erigontech/erigon/execution/tracing" "github.com/erigontech/erigon/execution/types" "github.com/erigontech/erigon/execution/types/accounts" @@ -108,7 +109,7 @@ type ( CanTransferFunc func(IntraBlockState, accounts.Address, uint256.Int) (bool, error) // TransferFunc is the signature of a transfer function - TransferFunc func(IntraBlockState, accounts.Address, accounts.Address, uint256.Int, bool) error + TransferFunc func(IntraBlockState, accounts.Address, accounts.Address, uint256.Int, bool, *chain.Rules) error // GetHashFunc returns the nth block hash in the blockchain // and is used by the BLOCKHASH EVM op code. diff --git a/execution/vm/gas_table_test.go b/execution/vm/gas_table_test.go index d7e04309b2b..b3ccfaa50a7 100644 --- a/execution/vm/gas_table_test.go +++ b/execution/vm/gas_table_test.go @@ -128,7 +128,7 @@ func TestEIP2200(t *testing.T) { vmctx := evmtypes.BlockContext{ CanTransfer: func(evmtypes.IntraBlockState, accounts.Address, uint256.Int) (bool, error) { return true, nil }, - Transfer: func(evmtypes.IntraBlockState, accounts.Address, accounts.Address, uint256.Int, bool) error { + Transfer: func(evmtypes.IntraBlockState, accounts.Address, accounts.Address, uint256.Int, bool, *chain.Rules) error { return nil }, } @@ -187,7 +187,7 @@ func TestCreateGas(t *testing.T) { vmctx := evmtypes.BlockContext{ CanTransfer: func(evmtypes.IntraBlockState, accounts.Address, uint256.Int) (bool, error) { return true, nil }, - Transfer: func(evmtypes.IntraBlockState, accounts.Address, accounts.Address, uint256.Int, bool) error { + Transfer: func(evmtypes.IntraBlockState, accounts.Address, accounts.Address, uint256.Int, bool, *chain.Rules) error { return nil }, } diff --git a/execution/vm/instructions.go b/execution/vm/instructions.go index ee739dfa340..c043f0fa7d9 100644 --- a/execution/vm/instructions.go +++ b/execution/vm/instructions.go @@ -29,6 +29,7 @@ import ( "github.com/erigontech/erigon/common" "github.com/erigontech/erigon/common/log/v3" + "github.com/erigontech/erigon/execution/protocol/misc" "github.com/erigontech/erigon/execution/protocol/params" "github.com/erigontech/erigon/execution/tracing" "github.com/erigontech/erigon/execution/types" @@ -1293,7 +1294,17 @@ func opSelfdestruct6780(pc uint64, interpreter *EVMInterpreter, scope *CallConte } interpreter.evm.IntraBlockState().SubBalance(callerAddr, balance, tracing.BalanceDecreaseSelfdestruct) interpreter.evm.IntraBlockState().AddBalance(beneficiaryAddr, balance, tracing.BalanceIncreaseSelfdestruct) - interpreter.evm.IntraBlockState().Selfdestruct6780(callerAddr) + newlyCreated, err := interpreter.evm.IntraBlockState().Selfdestruct6780(callerAddr) + if err != nil { + return pc, nil, err + } + if interpreter.evm.ChainRules().IsAmsterdam && !balance.IsZero() { + if callerAddr != beneficiaryAddr { + interpreter.evm.IntraBlockState().AddLog(misc.EthTransferLog(callerAddr, beneficiaryAddr, balance)) + } else if newlyCreated { + interpreter.evm.IntraBlockState().AddLog(misc.EthTransferLog(callerAddr, accounts.ZeroAddress, balance)) + } + } if interpreter.evm.Config().Tracer != nil && interpreter.evm.Config().Tracer.OnEnter != nil { interpreter.cfg.Tracer.OnEnter(interpreter.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiaryAddr, false, []byte{}, 0, balance, nil) } diff --git a/execution/vm/runtime/env.go b/execution/vm/runtime/env.go index 376a52ee54c..794797bceaa 100644 --- a/execution/vm/runtime/env.go +++ b/execution/vm/runtime/env.go @@ -21,7 +21,7 @@ package runtime import ( "github.com/erigontech/erigon/execution/protocol" - "github.com/erigontech/erigon/execution/protocol/rules" + "github.com/erigontech/erigon/execution/protocol/misc" "github.com/erigontech/erigon/execution/vm" "github.com/erigontech/erigon/execution/vm/evmtypes" ) @@ -34,7 +34,7 @@ func NewEnv(cfg *Config) *vm.EVM { blockContext := evmtypes.BlockContext{ CanTransfer: protocol.CanTransfer, - Transfer: rules.Transfer, + Transfer: misc.Transfer, GetHash: cfg.GetHashFn, Coinbase: cfg.Coinbase, BlockNumber: cfg.BlockNumber.Uint64(), diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index 88ff62a3903..c2d53700b66 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -1286,7 +1286,7 @@ func (c *Bor) CommitStates( } // BorTransfer transfer in Bor -func BorTransfer(db evmtypes.IntraBlockState, sender, recipient accounts.Address, amount uint256.Int, bailout bool) error { +func BorTransfer(db evmtypes.IntraBlockState, sender, recipient accounts.Address, amount uint256.Int, bailout bool, cr *chain.Rules) error { // get inputs before input1, err := db.GetBalance(sender) if err != nil { @@ -1297,7 +1297,7 @@ func BorTransfer(db evmtypes.IntraBlockState, sender, recipient accounts.Address return err } - rules.Transfer(db, sender, recipient, amount, bailout) + misc.Transfer(db, sender, recipient, amount, bailout, cr) output1, err := db.GetBalance(sender) if err != nil { diff --git a/rpc/jsonrpc/trace_adhoc_test.go b/rpc/jsonrpc/trace_adhoc_test.go index fec887755eb..79922cd3510 100644 --- a/rpc/jsonrpc/trace_adhoc_test.go +++ b/rpc/jsonrpc/trace_adhoc_test.go @@ -36,7 +36,7 @@ import ( "github.com/erigontech/erigon/common/math" "github.com/erigontech/erigon/db/kv" "github.com/erigontech/erigon/execution/protocol" - "github.com/erigontech/erigon/execution/protocol/rules" + "github.com/erigontech/erigon/execution/protocol/misc" "github.com/erigontech/erigon/execution/tests/mock" "github.com/erigontech/erigon/execution/tests/testutil" "github.com/erigontech/erigon/execution/tracing/tracers/config" @@ -398,7 +398,7 @@ func TestOeTracer(t *testing.T) { signer := types.MakeSigner(test.Genesis.Config, uint64(test.Context.Number), uint64(test.Context.Time)) context := evmtypes.BlockContext{ CanTransfer: protocol.CanTransfer, - Transfer: rules.Transfer, + Transfer: misc.Transfer, Coinbase: accounts.InternAddress(test.Context.Miner), BlockNumber: uint64(test.Context.Number), Time: uint64(test.Context.Time), From 8eca26e44a9f457a39ee8f960bbe1685ee07d5ab Mon Sep 17 00:00:00 2001 From: yperbasis Date: Thu, 22 Jan 2026 20:30:54 +0100 Subject: [PATCH 3/3] LogSelfDestructedAccounts --- execution/protocol/evm.go | 2 +- execution/protocol/misc/eip7708.go | 32 +++++++++++++++++++------ execution/protocol/rules/merge/merge.go | 2 +- execution/protocol/state_transition.go | 4 ++-- execution/stagedsync/exec3_parallel.go | 7 ++++-- execution/state/intra_block_state.go | 24 +++++++++++++++++-- execution/vm/evmtypes/evmtypes.go | 9 ++++++- execution/vm/instructions.go | 15 ++++++------ polygon/bor/bor.go | 2 +- 9 files changed, 73 insertions(+), 24 deletions(-) diff --git a/execution/protocol/evm.go b/execution/protocol/evm.go index a844218a2bf..1731e3b304d 100644 --- a/execution/protocol/evm.go +++ b/execution/protocol/evm.go @@ -88,7 +88,7 @@ func NewEVMBlockContext(header *types.Header, blockHashFunc func(n uint64) (comm postApplyMessageFunc = engine.GetPostApplyMessageFunc() } else { transferFunc = misc.Transfer - postApplyMessageFunc = nil + postApplyMessageFunc = misc.LogSelfDestructedAccounts } blockContext := evmtypes.BlockContext{ CanTransfer: CanTransfer, diff --git a/execution/protocol/misc/eip7708.go b/execution/protocol/misc/eip7708.go index ec6b093836b..8b7b394fa43 100644 --- a/execution/protocol/misc/eip7708.go +++ b/execution/protocol/misc/eip7708.go @@ -20,6 +20,8 @@ package misc import ( + "sort" + "github.com/holiman/uint256" "github.com/erigontech/erigon/common" @@ -33,14 +35,14 @@ import ( // EthTransferLog creates and ETH transfer log according to EIP-7708. // Specification: https://eips.ethereum.org/EIPS/eip-7708 -func EthTransferLog(from, to accounts.Address, amount uint256.Int) *types.Log { +func EthTransferLog(from, to common.Address, amount uint256.Int) *types.Log { amount32 := amount.Bytes32() return &types.Log{ Address: params.SystemAddress.Value(), Topics: []common.Hash{ params.EthTransferLogEvent, - from.Value().Hash(), - to.Value().Hash(), + from.Hash(), + to.Hash(), }, Data: amount32[:], } @@ -48,13 +50,13 @@ func EthTransferLog(from, to accounts.Address, amount uint256.Int) *types.Log { // EthSelfDestructLog creates and ETH self-destruct burn log according to EIP-7708. // Specification: https://eips.ethereum.org/EIPS/eip-7708 -func EthSelfDestructLog(from accounts.Address, amount uint256.Int) *types.Log { +func EthSelfDestructLog(from common.Address, amount uint256.Int) *types.Log { amount32 := amount.Bytes32() return &types.Log{ Address: params.SystemAddress.Value(), Topics: []common.Hash{ params.EthSelfDestructLogEvent, - from.Value().Hash(), + from.Hash(), }, Data: amount32[:], } @@ -72,8 +74,24 @@ func Transfer(db evmtypes.IntraBlockState, sender, recipient accounts.Address, a if err != nil { return err } - if rules.IsAmsterdam && !amount.IsZero() { - db.AddLog(EthTransferLog(sender, recipient, amount)) + if rules.IsAmsterdam && !amount.IsZero() { // EIP-7708 + db.AddLog(EthTransferLog(sender.Value(), recipient.Value(), amount)) } return nil } + +func LogSelfDestructedAccounts(ibs evmtypes.IntraBlockState, sender accounts.Address, coinbase accounts.Address, result *evmtypes.ExecutionResult, rules *chain.Rules) { + if !rules.IsAmsterdam { + return + } + // (EIP-7708) Emit SelfDestruct logs where accounts with non-empty balances have been deleted + removedWithBalance := ibs.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 { + ibs.AddLog(EthSelfDestructLog(sd.Address, sd.Balance)) + } + } +} diff --git a/execution/protocol/rules/merge/merge.go b/execution/protocol/rules/merge/merge.go index 219d4ff31a3..d810223812a 100644 --- a/execution/protocol/rules/merge/merge.go +++ b/execution/protocol/rules/merge/merge.go @@ -406,7 +406,7 @@ func (s *Merge) GetTransferFunc() evmtypes.TransferFunc { } func (s *Merge) GetPostApplyMessageFunc() evmtypes.PostApplyMessageFunc { - return s.eth1Engine.GetPostApplyMessageFunc() + return misc.LogSelfDestructedAccounts } func (s *Merge) Close() error { diff --git a/execution/protocol/state_transition.go b/execution/protocol/state_transition.go index 876591359c5..f7bd6d05f63 100644 --- a/execution/protocol/state_transition.go +++ b/execution/protocol/state_transition.go @@ -399,7 +399,7 @@ func (st *StateTransition) ApplyFrame() (*evmtypes.ExecutionResult, error) { } if st.evm.Context.PostApplyMessage != nil { - st.evm.Context.PostApplyMessage(st.state, msg.From(), coinbase, result) + st.evm.Context.PostApplyMessage(st.state, msg.From(), coinbase, result, rules) } return result, nil @@ -614,7 +614,7 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (result * result.BurntContractAddress = burntContractAddress if st.evm.Context.PostApplyMessage != nil { - st.evm.Context.PostApplyMessage(st.state, msg.From(), coinbase, result) + st.evm.Context.PostApplyMessage(st.state, msg.From(), coinbase, result, rules) } return result, nil diff --git a/execution/stagedsync/exec3_parallel.go b/execution/stagedsync/exec3_parallel.go index 733c37977d2..aef67a1ea0e 100644 --- a/execution/stagedsync/exec3_parallel.go +++ b/execution/stagedsync/exec3_parallel.go @@ -976,9 +976,11 @@ func (result *execResult) finalize(prevReceipt *types.Receipt, engine rules.Engi } ibs.SetTrace(txTask.Trace) + rules := txTask.EvmBlockContext.Rules(txTask.Config) + if task.IsBlockEnd() || txIndex < 0 { if blockNum == 0 || txTask.Config.IsByzantium(blockNum) { - if err := ibs.FinalizeTx(txTask.EvmBlockContext.Rules(txTask.Config), stateWriter); err != nil { + if err := ibs.FinalizeTx(rules, stateWriter); err != nil { return nil, nil, nil, err } } @@ -1022,6 +1024,7 @@ func (result *execResult) finalize(prevReceipt *types.Receipt, engine rules.Engi message.From(), result.Coinbase, &execResult, + rules, ) // capture postApplyMessageFunc side affects @@ -1043,7 +1046,7 @@ func (result *execResult) finalize(prevReceipt *types.Receipt, engine rules.Engi vm.SetTrace(false) if txTask.Config.IsByzantium(blockNum) { - ibs.FinalizeTx(txTask.EvmBlockContext.Rules(txTask.Config), stateWriter) + ibs.FinalizeTx(rules, stateWriter) } receipt, err := result.CreateNextReceipt(prevReceipt) diff --git a/execution/state/intra_block_state.go b/execution/state/intra_block_state.go index 821b4b24b0a..2b2183d326f 100644 --- a/execution/state/intra_block_state.go +++ b/execution/state/intra_block_state.go @@ -1184,7 +1184,7 @@ func (sdb *IntraBlockState) Selfdestruct(addr accounts.Address) (bool, error) { var zeroBalance uint256.Int -func (sdb *IntraBlockState) Selfdestruct6780(addr accounts.Address) (newlyCreated bool, err error) { +func (sdb *IntraBlockState) Selfdestruct6780(addr accounts.Address) (bool, error) { stateObject, err := sdb.getStateObject(addr) if err != nil { return false, err @@ -1199,9 +1199,11 @@ func (sdb *IntraBlockState) Selfdestruct6780(addr accounts.Address) (newlyCreate } if _, ok := types.ParseDelegation(code); !ok { sdb.Selfdestruct(addr) + return true, nil } } - return stateObject.newlyCreated, nil + // TODO(yperbasis) double check that returning false is OK here in the context of EIP-7708 + return false, nil } // SetTransientState sets transient storage for a given account. It @@ -1611,6 +1613,24 @@ func (sdb *IntraBlockState) FinalizeTx(chainRules *chain.Rules, stateWriter Stat return nil } +// GetRemovedAccountsWithBalance returns a list of 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 (sdb *IntraBlockState) GetRemovedAccountsWithBalance() (list []evmtypes.AddressAndBalance) { + for addr := range sdb.journal.dirties { + if obj, exist := sdb.stateObjects[addr]; exist && obj.selfdestructed { + if balance := obj.Balance(); !balance.IsZero() { + list = append(list, evmtypes.AddressAndBalance{Address: obj.address.Value(), Balance: balance}) + } + } + } + return list +} + func (sdb *IntraBlockState) SoftFinalise() { for addr := range sdb.journal.dirties { _, exist := sdb.stateObjects[addr] diff --git a/execution/vm/evmtypes/evmtypes.go b/execution/vm/evmtypes/evmtypes.go index c1cf4b85b07..f1f298069b1 100644 --- a/execution/vm/evmtypes/evmtypes.go +++ b/execution/vm/evmtypes/evmtypes.go @@ -117,15 +117,22 @@ type ( // PostApplyMessageFunc is an extension point to execute custom logic at the end of core.ApplyMessage. // It's used in Bor for AddFeeTransferLog or in ethereum to clear out the authority code at end of tx. - PostApplyMessageFunc func(ibs IntraBlockState, sender accounts.Address, coinbase accounts.Address, result *ExecutionResult) + PostApplyMessageFunc func(ibs IntraBlockState, sender accounts.Address, coinbase accounts.Address, result *ExecutionResult, chainRules *chain.Rules) ) +type AddressAndBalance struct { + Address common.Address + Balance uint256.Int +} + // IntraBlockState is an EVM database for full state querying. type IntraBlockState interface { SubBalance(accounts.Address, uint256.Int, tracing.BalanceChangeReason) error AddBalance(accounts.Address, uint256.Int, tracing.BalanceChangeReason) error GetBalance(accounts.Address) (uint256.Int, error) + GetRemovedAccountsWithBalance() []AddressAndBalance + AddLog(*types.Log) SetHooks(hooks *tracing.Hooks) diff --git a/execution/vm/instructions.go b/execution/vm/instructions.go index c043f0fa7d9..b927386a2d4 100644 --- a/execution/vm/instructions.go +++ b/execution/vm/instructions.go @@ -1288,21 +1288,22 @@ func opSelfdestruct6780(pc uint64, interpreter *EVMInterpreter, scope *CallConte beneficiary := scope.Stack.pop() callerAddr := scope.Contract.Address() beneficiaryAddr := accounts.InternAddress(beneficiary.Bytes20()) - balance, err := interpreter.evm.IntraBlockState().GetBalance(callerAddr) + ibs := interpreter.evm.IntraBlockState() + balance, err := ibs.GetBalance(callerAddr) if err != nil { return pc, nil, err } - interpreter.evm.IntraBlockState().SubBalance(callerAddr, balance, tracing.BalanceDecreaseSelfdestruct) - interpreter.evm.IntraBlockState().AddBalance(beneficiaryAddr, balance, tracing.BalanceIncreaseSelfdestruct) - newlyCreated, err := interpreter.evm.IntraBlockState().Selfdestruct6780(callerAddr) + ibs.SubBalance(callerAddr, balance, tracing.BalanceDecreaseSelfdestruct) + ibs.AddBalance(beneficiaryAddr, balance, tracing.BalanceIncreaseSelfdestruct) + selfDestructed, err := ibs.Selfdestruct6780(callerAddr) if err != nil { return pc, nil, err } if interpreter.evm.ChainRules().IsAmsterdam && !balance.IsZero() { if callerAddr != beneficiaryAddr { - interpreter.evm.IntraBlockState().AddLog(misc.EthTransferLog(callerAddr, beneficiaryAddr, balance)) - } else if newlyCreated { - interpreter.evm.IntraBlockState().AddLog(misc.EthTransferLog(callerAddr, accounts.ZeroAddress, balance)) + ibs.AddLog(misc.EthTransferLog(callerAddr.Value(), beneficiaryAddr.Value(), balance)) + } else if selfDestructed { + ibs.AddLog(misc.EthTransferLog(callerAddr.Value(), common.Address{}, balance)) } } if interpreter.evm.Config().Tracer != nil && interpreter.evm.Config().Tracer.OnEnter != nil { diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index c2d53700b66..4a6cf1cb87a 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -1318,7 +1318,7 @@ func (c *Bor) GetTransferFunc() evmtypes.TransferFunc { // AddFeeTransferLog adds fee transfer log into state // Deprecating transfer log and will be removed in future fork. PLEASE DO NOT USE this transfer log going forward. Parameters won't get updated as expected going forward with EIP1559 -func AddFeeTransferLog(ibs evmtypes.IntraBlockState, sender accounts.Address, coinbase accounts.Address, result *evmtypes.ExecutionResult) { +func AddFeeTransferLog(ibs evmtypes.IntraBlockState, sender accounts.Address, coinbase accounts.Address, result *evmtypes.ExecutionResult, _ *chain.Rules) { output1 := result.SenderInitBalance output2 := result.CoinbaseInitBalance addTransferLog(