EIP-6780 is an Ethereum protocol upgrade that changes how the SELFDESTRUCT opcode behaves. The core change: SELFDESTRUCT now fully deletes a contract's code, storage, and account only when called within the same transaction as the contract's deployment; in every other case (the overwhelming majority of real-world uses), it merely transfers the contract's funds out while leaving its code and storage data entirely intact on the chain — a complete departure from SELFDESTRUCT's original behavior of making the entire contract disappear after execution.
This change exists because Ethereum's future plans to adopt the Verkle tree state storage architecture, under which account data gets split across multiple keys, making it technically impractical and inefficient to atomically delete all of an account's data in one operation. EIP-6780 chose to adjust SELFDESTRUCT's behavior to fit within the new architecture's constraints, rather than letting the entire state tree design become unreasonably complex just to accommodate the old deletion logic — a classic engineering tradeoff of sacrificing an old feature's full behavior in exchange for future scalability.
The concrete rule splits into two branches. Branch one: SELFDESTRUCT called within the same transaction as the contract's deployment — the old behavior holds, with code, storage, and account all deleted, common in factory-contract patterns using disposable helper contracts. Branch two: SELFDESTRUCT called sometime after deployment has already completed — only the fund-transfer action executes, while the contract's code and previously written storage data stay entirely intact and queryable on the chain, with the account itself still existing. For an analyst to determine the current state of a contract that "self-destructed," two things must be checked separately: whether the contract's current balance is zero (funds transferred out), and whether the contract's code and storage can still be queried (in the vast majority of cases, yes).
The practical implication: if you're doing onchain due diligence or tracing a contract's historical fund flow or vulnerability record, and you see that "this contract executed SELFDESTRUCT," don't treat that as a signal meaning "this contract no longer exists and can be ignored." The correct move is to check further: whether the contract's code and storage data are still queryable (usually yes) — its past transaction history and logic remain complete onchain evidence, and none of it disappears or becomes less trustworthy just because the contract executed a self-destruct instruction.
In Ethereum's early design, SELFDESTRUCT was an opcode a Smart Contract could invoke that would transfer any remaining funds to a specified address while deleting the contract's code, storage, and the account itself from chain state entirely. "Disappear" was an apt description — the contract account simply ceased to exist afterward. This was originally designed to let developers free up state space when a contract was no longer needed, with a partial gas refund as a bonus (deleting data used to refund part of the gas cost).
The problem traces back to Ethereum's long-term scalability roadmap. Ethereum plans to adopt a new state storage structure called Verkle trees, under which account data gets split across multiple separate keys. Under that architecture, atomically deleting all of an account's associated data in one shot becomes technically impractical — not impossible, but it would make the entire state tree design unreasonably complex and inefficient. EIP-6780's solution wasn't to force the entire architecture to accommodate the old deletion logic — it went the other way, adjusting how SELFDESTRUCT behaves to fit within the new architecture's constraints.
The adjusted rule: if SELFDESTRUCT is called within the same transaction as the contract's deployment, it still behaves as before — fully deleting the code, storage, and account. But if it's called sometime after deployment has already completed (the overwhelming majority of real-world use cases), it now only executes the fund-transfer action, while the contract's code and storage data stay exactly as they are on the chain. This design preserves the legitimate use case common to factory contract patterns — disposable helper contracts that self-destruct the moment they're deployed — while cutting out the deletion behavior that was causing problems.
This means an analyst looking at a contract that "executed SELFDESTRUCT" can no longer simply assume it has disappeared from the chain. The more accurate picture: the contract's balance drops to zero, the funds have moved out, but its code can still be queried, and the storage data it wrote in the past can still be read — the contract simply won't be normally called or interacted with by anyone anymore, making it a genuine empty shell. For anyone doing onchain due diligence or tracing historical fund flows, this distinction matters: a contract that was "actually deleted" and one that's "zeroed out but still has its code intact" carry completely different meanings for risk assessment — the latter's historical logic, past vulnerability record, and former attack surface can all still be fully examined, and none of it vanishes just because the contract "looks" self-destructed.
Previously, judging whether a contract was "dead" could be simplified to a binary question: had SELFDESTRUCT ever been called? After EIP-6780, that question has to be split into at least two layers: does the contract hold a balance (have its funds been moved out), and can its code and storage still be queried (in the vast majority of cases, the answer is yes). An analytics platform that only checks "was a SELFDESTRUCT event ever triggered" and labels that contract as "gone," removing it from a tracking list, may actually be missing a contract that still carries its full historical data — and in theory could still be interacted with through some remaining permission.