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.