From 9dda9f02b29391d0b1136306679f75c1ddef3eec Mon Sep 17 00:00:00 2001 From: lightclient Date: Mon, 12 Jan 2026 08:39:32 -0700 Subject: [PATCH] core/vm: improve comments in self destruct --- core/vm/instructions.go | 55 ++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 60fd70d90d..09e1ba35fa 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -876,21 +876,25 @@ func opStop(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { } func opSelfdestruct(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { - beneficiary := scope.Stack.pop() - balance := evm.StateDB.GetBalance(scope.Contract.Address()) + var ( + this = scope.Contract.Address() + balance = evm.StateDB.GetBalance(this) + top = scope.Stack.pop() + beneficiary = common.Address(top.Bytes20()) + ) // The funds are burned immediately if the beneficiary is the caller itself, // in this case, the beneficiary's balance is not increased. - if beneficiary.Bytes20() != scope.Contract.Address() { - evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct) + if beneficiary != this { + evm.StateDB.AddBalance(beneficiary, balance, tracing.BalanceIncreaseSelfdestruct) } // Clear any leftover funds for the account being destructed. - evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct) - evm.StateDB.SelfDestruct(scope.Contract.Address()) + evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct) + evm.StateDB.SelfDestruct(this) if tracer := evm.Config.Tracer; tracer != nil { if tracer.OnEnter != nil { - tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig()) + tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), this, beneficiary, []byte{}, 0, balance.ToBig()) } if tracer.OnExit != nil { tracer.OnExit(evm.depth, []byte{}, 0, nil, false) @@ -900,28 +904,35 @@ func opSelfdestruct(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { } func opSelfdestruct6780(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { - beneficiary := scope.Stack.pop() - balance := evm.StateDB.GetBalance(scope.Contract.Address()) + var ( + this = scope.Contract.Address() + balance = evm.StateDB.GetBalance(this) + top = scope.Stack.pop() + beneficiary = common.Address(top.Bytes20()) + ) - if evm.StateDB.IsNewContract(scope.Contract.Address()) { - // If the contract is not preexisting, the balance is immediately burned - // on selfdestruct-to-self. In this case, the beneficiary's balance is - // not increased. - if scope.Contract.Address() != beneficiary.Bytes20() { - evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct) + if evm.StateDB.IsNewContract(this) { + // Contract is newly created in this transaction, so it will be actually + // deleted from the state. + if this == beneficiary { + // Since the contract will be deleted from state, it isn't necessary to + // also subtract the balance beforehand as it will affect the tracing. + } else { + // Otherwise, we can proceed with transfer. + evm.StateDB.AddBalance(beneficiary, balance, tracing.BalanceIncreaseSelfdestruct) } - evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct) + evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct) } else { - // If the contract is preexisting, send all Ether in the account to the - // target. Note the balance isn't burned on selfdestruct-to-self. - evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct) - evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct) + // Contract already exists in the state, therefore it will send it's full + // balance and remain in the state. + evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct) + evm.StateDB.AddBalance(beneficiary, balance, tracing.BalanceIncreaseSelfdestruct) } - evm.StateDB.SelfDestruct6780(scope.Contract.Address()) + evm.StateDB.SelfDestruct6780(this) if tracer := evm.Config.Tracer; tracer != nil { if tracer.OnEnter != nil { - tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig()) + tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), this, beneficiary, []byte{}, 0, balance.ToBig()) } if tracer.OnExit != nil { tracer.OnExit(evm.depth, []byte{}, 0, nil, false)