Add a SET_INDESTRUCTIBLE (0xA8) opcode that prevents the contract from calling SELFDESTRUCT (0xff).


Should it be permanent or should there be a way to rollback?

The flag set by the opcode would last for the duration of the transaction, so it is temporary (though if the first byte of a contract is the opcode then of course it will trigger every time and be unavoidable, which is the intention).

Can this new OPCODE be used to signal if the contract implement or not self destruct?

If is set to false, then you can’t destroy that specific contract.


If the first byte of the code of a contract is this opcode, then that contract cannot selfdestruct.

1 Like

I’m thinking more into if you have implement the self destruct function the opcode is “true”. Is not if is possible to remove the contract, but more this contract can everything is place to be removed.


Basically can we inside a smart contract know that other smart contract can be removed.

Is important in the case when a dev want to whitelist smart contracts on chain.

I like this EIP. It makes contracts and libraries safer.

It makes proxy contracts and diamonds safer because they rely on delegatecall which can pull in code from other contracts.

This EIP prevents delegatecall from accidentally or maliciously destroying proxy contracts and diamonds and prevents the contracts/libraries that proxy contracts and diamonds rely on from disappearing. This is good.

1 Like

The intended use case would be for contracts to make their first byte of code be the SET_INDESTRUCTIBLE opcode if they wish…

However, the spec doesn’t say what should happen if SET_INDESTRUCTIBLE is encountered on PC!=0

Some other questions.

  1. Let’s say we have C with SET_INDESTRUCTIBLE at 0. Contract X does delegatecall(c) && selfdestruct. Does C successfully selfdestruct?
  2. Same scenarion with C. What about callcode(c)?

In general, is the globals.indestructible scoped? I assume it is (by which I mean it’s journalled, and scope-revertals removes stuff from it)

  1. I think that if SET_INDESTRUCTIBLE is encountered on PC!=0, it should be treated as a no-op to avoid any weird edge cases. However, forcing it to be the first byte does make its use case less flexible and I’m open to lifting this restriction.
  2. C should not successfully self destruct when using delegatecall if it is set as indestructible.
  3. C should also not successfully self destruct when using callcode if it is set as indestructible.

I also believe SET_INDESTRUCTIBLE should be implemented as a variable local to each execution frame. I think it is unnecessary to make it a global variable, as the delegatecall/callcode edge case can still be resolved with a local boolean variable implementation.

Proposed update to EIP-2937 spec: https://github.com/ethereum/EIPs/pull/3186
Local variable implementation in geth client: https://github.com/lightclient/go-ethereum/pull/7