2

I'm wondering about how selfdestruct() actually works. Does it actually delete contract codes from the storage? Or just delete the contract address from state trie? If just deleting the contract address from state trie, does other new contract code overwrite it?

1 Answer 1

2

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.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.