Skip to main content
added 459 characters in body
Source Link
Nulik
  • 4.1k
  • 1
  • 19
  • 30

One additional note:

This line in statedb.Suicide() function:

stateObject.data.Balance = new(big.Int)

clears the balance, so, if you call SELFDESTRUCT on a contract, and you get it wrong with the address, like for example sending funds to the contract itself, instead of the owner, the balance of the contract is ZEROed. I recently found this was a case in this transaction https://etherscan.io/tx/0x52676b10cf1d1240355e8fcd1154a99327626bd3094cb7ff685a928bdec5b137

One additional note:

This line in statedb.Suicide() function:

stateObject.data.Balance = new(big.Int)

clears the balance, so, if you call SELFDESTRUCT on a contract, and you get it wrong with the address, like for example sending funds to the contract itself, instead of the owner, the balance of the contract is ZEROed. I recently found this was a case in this transaction https://etherscan.io/tx/0x52676b10cf1d1240355e8fcd1154a99327626bd3094cb7ff685a928bdec5b137

Source Link
Nulik
  • 4.1k
  • 1
  • 19
  • 30

It is marked as suicided in the state trie and the code is not cleared, it stays there forever.

FYI:

func opSuicide(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
    balance := evm.StateDB.GetBalance(contract.Address())
    evm.StateDB.AddBalance(common.BigToAddress(stack.pop()), balance)

    evm.StateDB.Suicide(contract.Address())
    return nil, nil
}

// Suicide marks the given account as suicided.
// This clears the account balance.
//
// The account's state object is still available until the state is committed,
// getStateObject will return a non-nil account after Suicide.
func (self *StateDB) Suicide(addr common.Address) bool {
    stateObject := self.getStateObject(addr)
    if stateObject == nil {
        return false
    }
    self.journal = append(self.journal, suicideChange{
        account:     &addr,
        prev:        stateObject.suicided,
        prevbalance: new(big.Int).Set(stateObject.Balance()),
    })
    stateObject.markSuicided()
    stateObject.data.Balance = new(big.Int)

    return true
}

An account can only be deleted from State Trie if it is empty. Where empty is defined as:

// Empty returns whether the state object is either non-existent
// or empty according to the EIP161 specification (balance = nonce = code = 0)
func (self *StateDB) Empty(addr common.Address) bool {
    so := self.getStateObject(addr)
    return so == nil || so.empty()
}


// empty returns whether the account is considered empty.
func (s *stateObject) empty() bool {
    return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash)
}

In your case, there is some code, so, the object is not empty.