mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 02:10:46 +00:00
core: replace suicide with selfdestruct to improve code consistency (#27716)
This commit is contained in:
parent
80967d52f6
commit
0f737b4725
12 changed files with 55 additions and 51 deletions
|
|
@ -89,7 +89,7 @@ func (t *TradingStateDB) Error() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exist reports whether the given orderId address exists in the state.
|
// Exist reports whether the given orderId address exists in the state.
|
||||||
// Notably this also returns true for suicided exchanges.
|
// Notably this also returns true for self-destructed exchanges.
|
||||||
func (t *TradingStateDB) Exist(addr common.Hash) bool {
|
func (t *TradingStateDB) Exist(addr common.Hash) bool {
|
||||||
return t.getStateExchangeObject(addr) != nil
|
return t.getStateExchangeObject(addr) != nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ func (ls *LendingStateDB) Error() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exist reports whether the given tradeId address exists in the state.
|
// Exist reports whether the given tradeId address exists in the state.
|
||||||
// Notably this also returns true for suicided lenddinges.
|
// Notably this also returns true for self-destructed lenddinges.
|
||||||
func (ls *LendingStateDB) Exist(addr common.Hash) bool {
|
func (ls *LendingStateDB) Exist(addr common.Hash) bool {
|
||||||
return ls.getLendingExchange(addr) != nil
|
return ls.getLendingExchange(addr) != nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import (
|
||||||
var (
|
var (
|
||||||
// ErrNoCode is returned by call and transact operations for which the requested
|
// ErrNoCode is returned by call and transact operations for which the requested
|
||||||
// recipient contract to operate on does not exist in the state db or does not
|
// recipient contract to operate on does not exist in the state db or does not
|
||||||
// have any code associated with it (i.e. suicided).
|
// have any code associated with it (i.e. self-destructed).
|
||||||
ErrNoCode = errors.New("no contract code at given address")
|
ErrNoCode = errors.New("no contract code at given address")
|
||||||
|
|
||||||
// ErrNoPendingState is raised when attempting to perform a pending state action
|
// ErrNoPendingState is raised when attempting to perform a pending state action
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,9 @@ type (
|
||||||
resetObjectChange struct {
|
resetObjectChange struct {
|
||||||
prev *stateObject
|
prev *stateObject
|
||||||
}
|
}
|
||||||
suicideChange struct {
|
selfDestructChange struct {
|
||||||
account *common.Address
|
account *common.Address
|
||||||
prev bool // whether account had already suicided
|
prev bool // whether account had already self-destructed
|
||||||
prevbalance *big.Int
|
prevbalance *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,10 +104,10 @@ func (ch resetObjectChange) undo(s *StateDB) {
|
||||||
s.setStateObject(ch.prev)
|
s.setStateObject(ch.prev)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch suicideChange) undo(s *StateDB) {
|
func (ch selfDestructChange) undo(s *StateDB) {
|
||||||
obj := s.getStateObject(*ch.account)
|
obj := s.getStateObject(*ch.account)
|
||||||
if obj != nil {
|
if obj != nil {
|
||||||
obj.suicided = ch.prev
|
obj.selfDestructed = ch.prev
|
||||||
obj.setBalance(ch.prevbalance)
|
obj.setBalance(ch.prevbalance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,10 +61,10 @@ func (s Storage) Copy() Storage {
|
||||||
// Account values can be accessed and modified through the object.
|
// Account values can be accessed and modified through the object.
|
||||||
// Finally, call CommitTrie to write the modified storage trie into a database.
|
// Finally, call CommitTrie to write the modified storage trie into a database.
|
||||||
type stateObject struct {
|
type stateObject struct {
|
||||||
address common.Address
|
|
||||||
addrHash common.Hash // hash of ethereum address of the account
|
|
||||||
data Account
|
|
||||||
db *StateDB
|
db *StateDB
|
||||||
|
address common.Address // address of ethereum account
|
||||||
|
addrHash common.Hash // hash of ethereum address of the account
|
||||||
|
data Account // Account data with all mutations applied in the scope of block
|
||||||
|
|
||||||
// DB error.
|
// DB error.
|
||||||
// State objects are used by the consensus core and VM which are
|
// State objects are used by the consensus core and VM which are
|
||||||
|
|
@ -82,13 +82,20 @@ type stateObject struct {
|
||||||
fakeStorage Storage // Fake storage which constructed by caller for debugging purpose.
|
fakeStorage Storage // Fake storage which constructed by caller for debugging purpose.
|
||||||
|
|
||||||
// Cache flags.
|
// Cache flags.
|
||||||
// When an object is marked suicided it will be delete from the trie
|
|
||||||
// during the "update" phase of the state transition.
|
|
||||||
dirtyCode bool // true if the code was updated
|
dirtyCode bool // true if the code was updated
|
||||||
suicided bool
|
|
||||||
touched bool
|
// Flag whether the account was marked as self-destructed. The self-destructed
|
||||||
deleted bool
|
// account is still accessible in the scope of same transaction.
|
||||||
onDirty func(addr common.Address) // Callback method to mark a state object newly dirty
|
selfDestructed bool
|
||||||
|
|
||||||
|
// Flag whether the account was marked as deleted. A self-destructed account
|
||||||
|
// or an account that is considered as empty will be marked as deleted at
|
||||||
|
// the end of transaction and no longer accessible anymore.
|
||||||
|
deleted bool
|
||||||
|
|
||||||
|
touched bool
|
||||||
|
|
||||||
|
onDirty func(addr common.Address) // Callback method to mark a state object newly dirty
|
||||||
}
|
}
|
||||||
|
|
||||||
// empty returns whether the account is considered empty.
|
// empty returns whether the account is considered empty.
|
||||||
|
|
@ -136,8 +143,8 @@ func (s *stateObject) setError(err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stateObject) markSuicided() {
|
func (s *stateObject) markSelfdestructed() {
|
||||||
s.suicided = true
|
s.selfDestructed = true
|
||||||
if s.onDirty != nil {
|
if s.onDirty != nil {
|
||||||
s.onDirty(s.Address())
|
s.onDirty(s.Address())
|
||||||
s.onDirty = nil
|
s.onDirty = nil
|
||||||
|
|
@ -363,7 +370,7 @@ func (s *stateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *
|
||||||
stateObject.code = s.code
|
stateObject.code = s.code
|
||||||
stateObject.dirtyStorage = s.dirtyStorage.Copy()
|
stateObject.dirtyStorage = s.dirtyStorage.Copy()
|
||||||
stateObject.cachedStorage = s.dirtyStorage.Copy()
|
stateObject.cachedStorage = s.dirtyStorage.Copy()
|
||||||
stateObject.suicided = s.suicided
|
stateObject.selfDestructed = s.selfDestructed
|
||||||
stateObject.dirtyCode = s.dirtyCode
|
stateObject.dirtyCode = s.dirtyCode
|
||||||
stateObject.deleted = s.deleted
|
stateObject.deleted = s.deleted
|
||||||
return stateObject
|
return stateObject
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
checker "gopkg.in/check.v1"
|
checker "gopkg.in/check.v1"
|
||||||
|
|
@ -152,7 +152,7 @@ func TestSnapshot2(t *testing.T) {
|
||||||
so0.SetBalance(big.NewInt(42))
|
so0.SetBalance(big.NewInt(42))
|
||||||
so0.SetNonce(43)
|
so0.SetNonce(43)
|
||||||
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
|
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
|
||||||
so0.suicided = false
|
so0.selfDestructed = false
|
||||||
so0.deleted = false
|
so0.deleted = false
|
||||||
state.setStateObject(so0)
|
state.setStateObject(so0)
|
||||||
|
|
||||||
|
|
@ -164,7 +164,7 @@ func TestSnapshot2(t *testing.T) {
|
||||||
so1.SetBalance(big.NewInt(52))
|
so1.SetBalance(big.NewInt(52))
|
||||||
so1.SetNonce(53)
|
so1.SetNonce(53)
|
||||||
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
|
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
|
||||||
so1.suicided = true
|
so1.selfDestructed = true
|
||||||
so1.deleted = true
|
so1.deleted = true
|
||||||
state.setStateObject(so1)
|
state.setStateObject(so1)
|
||||||
|
|
||||||
|
|
@ -224,8 +224,8 @@ func compareStateObjects(so0, so1 *stateObject, t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if so0.suicided != so1.suicided {
|
if so0.selfDestructed != so1.selfDestructed {
|
||||||
t.Fatalf("suicided mismatch: have %v, want %v", so0.suicided, so1.suicided)
|
t.Fatalf("self-destructed mismatch: have %v, want %v", so0.selfDestructed, so1.selfDestructed)
|
||||||
}
|
}
|
||||||
if so0.deleted != so1.deleted {
|
if so0.deleted != so1.deleted {
|
||||||
t.Fatalf("Deleted mismatch: have %v, want %v", so0.deleted, so1.deleted)
|
t.Fatalf("Deleted mismatch: have %v, want %v", so0.deleted, so1.deleted)
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,7 @@ func (s *StateDB) AddRefund(gas uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exist reports whether the given account address exists in the state.
|
// Exist reports whether the given account address exists in the state.
|
||||||
// Notably this also returns true for suicided accounts.
|
// Notably this also returns true for self-destructed accounts.
|
||||||
func (s *StateDB) Exist(addr common.Address) bool {
|
func (s *StateDB) Exist(addr common.Address) bool {
|
||||||
return s.getStateObject(addr) != nil
|
return s.getStateObject(addr) != nil
|
||||||
}
|
}
|
||||||
|
|
@ -336,10 +336,10 @@ func (s *StateDB) StorageTrie(addr common.Address) Trie {
|
||||||
return cpy.updateTrie(s.db)
|
return cpy.updateTrie(s.db)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) HasSuicided(addr common.Address) bool {
|
func (s *StateDB) HasSelfDestructed(addr common.Address) bool {
|
||||||
stateObject := s.getStateObject(addr)
|
stateObject := s.getStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
return stateObject.suicided
|
return stateObject.selfDestructed
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -401,25 +401,23 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suicide marks the given account as suicided.
|
// SelfDestruct marks the given account as selfdestructed.
|
||||||
// This clears the account balance.
|
// This clears the account balance.
|
||||||
//
|
//
|
||||||
// The account's state object is still available until the state is committed,
|
// The account's state object is still available until the state is committed,
|
||||||
// getStateObject will return a non-nil account after Suicide.
|
// getStateObject will return a non-nil account after SelfDestruct.
|
||||||
func (s *StateDB) Suicide(addr common.Address) bool {
|
func (s *StateDB) SelfDestruct(addr common.Address) {
|
||||||
stateObject := s.getStateObject(addr)
|
stateObject := s.getStateObject(addr)
|
||||||
if stateObject == nil {
|
if stateObject == nil {
|
||||||
return false
|
return
|
||||||
}
|
}
|
||||||
s.journal = append(s.journal, suicideChange{
|
s.journal = append(s.journal, selfDestructChange{
|
||||||
account: &addr,
|
account: &addr,
|
||||||
prev: stateObject.suicided,
|
prev: stateObject.selfDestructed,
|
||||||
prevbalance: new(big.Int).Set(stateObject.Balance()),
|
prevbalance: new(big.Int).Set(stateObject.Balance()),
|
||||||
})
|
})
|
||||||
stateObject.markSuicided()
|
stateObject.markSelfdestructed()
|
||||||
stateObject.data.Balance = new(big.Int)
|
stateObject.data.Balance = new(big.Int)
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTransientState sets transient storage for a given account. It
|
// SetTransientState sets transient storage for a given account. It
|
||||||
|
|
@ -679,7 +677,7 @@ func (s *StateDB) GetRefund() uint64 {
|
||||||
func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
||||||
for addr := range s.stateObjectsDirty {
|
for addr := range s.stateObjectsDirty {
|
||||||
stateObject := s.stateObjects[addr]
|
stateObject := s.stateObjects[addr]
|
||||||
if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) {
|
if stateObject.selfDestructed || (deleteEmptyObjects && stateObject.empty()) {
|
||||||
s.deleteStateObject(stateObject)
|
s.deleteStateObject(stateObject)
|
||||||
} else {
|
} else {
|
||||||
stateObject.updateRoot(s.db)
|
stateObject.updateRoot(s.db)
|
||||||
|
|
@ -710,7 +708,7 @@ func (s *StateDB) SetTxContext(thash common.Hash, ti int) {
|
||||||
s.txIndex = ti
|
s.txIndex = ti
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSuicides flags the suicided objects for deletion so that it
|
// DeleteSuicides flags the self-destructed objects for deletion so that it
|
||||||
// won't be referenced again when called / queried up on.
|
// won't be referenced again when called / queried up on.
|
||||||
//
|
//
|
||||||
// DeleteSuicides should not be used for consensus related updates
|
// DeleteSuicides should not be used for consensus related updates
|
||||||
|
|
@ -724,7 +722,7 @@ func (s *StateDB) DeleteSuicides() {
|
||||||
|
|
||||||
// If the object has been removed by a suicide
|
// If the object has been removed by a suicide
|
||||||
// flag the object as deleted.
|
// flag the object as deleted.
|
||||||
if stateObject.suicided {
|
if stateObject.selfDestructed {
|
||||||
stateObject.deleted = true
|
stateObject.deleted = true
|
||||||
}
|
}
|
||||||
delete(s.stateObjectsDirty, addr)
|
delete(s.stateObjectsDirty, addr)
|
||||||
|
|
@ -745,7 +743,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error)
|
||||||
for addr, stateObject := range s.stateObjects {
|
for addr, stateObject := range s.stateObjects {
|
||||||
_, isDirty := s.stateObjectsDirty[addr]
|
_, isDirty := s.stateObjectsDirty[addr]
|
||||||
switch {
|
switch {
|
||||||
case stateObject.suicided || (isDirty && deleteEmptyObjects && stateObject.empty()):
|
case stateObject.selfDestructed || (isDirty && deleteEmptyObjects && stateObject.empty()):
|
||||||
// If the object has been removed, don't bother syncing it
|
// If the object has been removed, don't bother syncing it
|
||||||
// and just mark it for deletion in the trie.
|
// and just mark it for deletion in the trie.
|
||||||
s.deleteStateObject(stateObject)
|
s.deleteStateObject(stateObject)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import (
|
||||||
"testing/quick"
|
"testing/quick"
|
||||||
|
|
||||||
check "gopkg.in/check.v1"
|
check "gopkg.in/check.v1"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
|
@ -261,9 +260,9 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Suicide",
|
name: "SelfDestruct",
|
||||||
fn: func(a testAction, s *StateDB) {
|
fn: func(a testAction, s *StateDB) {
|
||||||
s.Suicide(addr)
|
s.SelfDestruct(addr)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -405,7 +404,7 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
|
||||||
}
|
}
|
||||||
// Check basic accessor methods.
|
// Check basic accessor methods.
|
||||||
checkeq("Exist", state.Exist(addr), checkstate.Exist(addr))
|
checkeq("Exist", state.Exist(addr), checkstate.Exist(addr))
|
||||||
checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr))
|
checkeq("HasSelfDestructed", state.HasSelfDestructed(addr), checkstate.HasSelfDestructed(addr))
|
||||||
checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr))
|
checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr))
|
||||||
checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr))
|
checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr))
|
||||||
checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr))
|
checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr))
|
||||||
|
|
|
||||||
|
|
@ -469,7 +469,7 @@ func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !evm.StateDB.HasSuicided(contract.Address()) {
|
if !evm.StateDB.HasSelfDestructed(contract.Address()) {
|
||||||
evm.StateDB.AddRefund(params.SelfdestructRefundGas)
|
evm.StateDB.AddRefund(params.SelfdestructRefundGas)
|
||||||
}
|
}
|
||||||
return gas, nil
|
return gas, nil
|
||||||
|
|
|
||||||
|
|
@ -415,7 +415,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
||||||
// If the precompile account is not transferred any amount on a private or
|
// If the precompile account is not transferred any amount on a private or
|
||||||
// customized chain, the return value will be zero.
|
// customized chain, the return value will be zero.
|
||||||
//
|
//
|
||||||
// (5) Caller tries to get the code hash for an account which is marked as suicided
|
// (5) Caller tries to get the code hash for an account which is marked as self-destructed
|
||||||
//
|
//
|
||||||
// in the current transaction, the code hash of this account should be returned.
|
// in the current transaction, the code hash of this account should be returned.
|
||||||
//
|
//
|
||||||
|
|
@ -837,7 +837,7 @@ func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
||||||
beneficiary := scope.Stack.pop()
|
beneficiary := scope.Stack.pop()
|
||||||
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
|
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
|
||||||
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
|
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
|
||||||
interpreter.evm.StateDB.Suicide(scope.Contract.Address())
|
interpreter.evm.StateDB.SelfDestruct(scope.Contract.Address())
|
||||||
if interpreter.evm.Config.Debug {
|
if interpreter.evm.Config.Debug {
|
||||||
interpreter.evm.Config.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
|
interpreter.evm.Config.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
|
||||||
interpreter.evm.Config.Tracer.CaptureExit([]byte{}, 0, nil)
|
interpreter.evm.Config.Tracer.CaptureExit([]byte{}, 0, nil)
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,11 @@ type StateDB interface {
|
||||||
GetTransientState(addr common.Address, key common.Hash) common.Hash
|
GetTransientState(addr common.Address, key common.Hash) common.Hash
|
||||||
SetTransientState(addr common.Address, key, value common.Hash)
|
SetTransientState(addr common.Address, key, value common.Hash)
|
||||||
|
|
||||||
Suicide(common.Address) bool
|
SelfDestruct(common.Address)
|
||||||
HasSuicided(common.Address) bool
|
HasSelfDestructed(common.Address) bool
|
||||||
|
|
||||||
// Exist reports whether the given account exists in state.
|
// Exist reports whether the given account exists in state.
|
||||||
// Notably this should also return true for suicided accounts.
|
// Notably this should also return true for self-destructed accounts.
|
||||||
Exist(common.Address) bool
|
Exist(common.Address) bool
|
||||||
// Empty returns whether the given account is empty. Empty
|
// Empty returns whether the given account is empty. Empty
|
||||||
// is defined according to EIP161 (balance = nonce = code = 0).
|
// is defined according to EIP161 (balance = nonce = code = 0).
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
|
||||||
if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
|
if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
|
||||||
gas += params.CreateBySelfdestructGas
|
gas += params.CreateBySelfdestructGas
|
||||||
}
|
}
|
||||||
if refundsEnabled && !evm.StateDB.HasSuicided(contract.Address()) {
|
if refundsEnabled && !evm.StateDB.HasSelfDestructed(contract.Address()) {
|
||||||
evm.StateDB.AddRefund(params.SelfdestructRefundGas)
|
evm.StateDB.AddRefund(params.SelfdestructRefundGas)
|
||||||
}
|
}
|
||||||
return gas, nil
|
return gas, nil
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue