TLDR: The selfdestruct↔revive pattern stays working, but instead of deleting accounts, we use a special value in the nonce
field to distinguish deactivated accounts.
From the motivation of EIP-4758:
The
SELFDESTRUCT
opcode requires large changes to the state of an account, in particular removing all code and storage. This will not be possible in the future with Verkle trees: Each account will be stored in many different account keys, which will not be obviously connected to the root account.
EIP-4758 proposes to:
- The
SELFDESTRUCT
opcode is renamed toSENDALL
, and now only immediately moves all ETH in the account to the target; it no longer destroys code or storage or alters the nonce- All refunds related to
SELFDESTRUCT
are removed
Concerns have been voiced that a number of contracts depend on a selfdestruct↔revive pattern, which would be broken by this change.
Here’s an alternative slightly-hackish idea. Haven’t investigated its merits too much, but wanted to float it.
Since EIP-2681 it is ensured that the account.nonce
field can never exceed 2^64-1
. We can use this to our advantage.
SELFDESTRUCT
continues to behave almost the same as today, but instead of removing the account, it will leave most properties of the account intact, with the exception of two:
- transfer all value and set
balance
to0
, - set
nonce
to2^64
.
- Modify account execution (triggered both via external transactions or
CALL*
), such that execution fails if thenonce
equals2^64
.
- Note that the account can still receive non-executable value transfers (such as coinbase transactions).
- Another option would be to just behave like an account without code upon execution, i.e. return success and no data.
-
Modify
CREATE2
such that it allows account creation if thenonce
equals2^64
. -
Rename the
SELFDESTRUCT
instruction toDEACTIVATE
, since the semantics of “account re-creation” are changed: the old storage items will remain, and newly deployed code must be aware of this.
This option I think would accomplish the goal of removing unbounded tree changes, while not breaking existing contracts. Account/storage waste would remain, but that remains in-place with EIP-4758 too. Additionally, for deactivated accounts, the codehash and other inspectable properties would remain the same, just as with EIP-4758.
P.S. Doesn’t the Contracts deployed before EIP-161 behave differently.nonce
of an account-with-code start at 1
and not 0
? If it does, could also use 0
as the magic value.
P.P.S. If we want external observability of deactivated accounts, perhaps an EXTNONCE
opcode would be useful.