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.