EIP-6188, EIP-6189, and EIP-6190: The SELFDESTRUCT trilogy

This is the discussion link for EIP-6188, EIP-6189, and EIP-6190.

The goal of these EIPs is to modify SELFDESTRUCT in a mostly non-breaking manner to support Verkle trees and to limit the number of changes that are to be performed.

3 Likes

First thing’s first: why three EIPs?

It’s because I want them to be usable independently of each other. It’s quite possible that EIPs (i.e. I am planning on making EIPs that) can use the magic value of EIP-6188 and don’t necessarily need the selfdestruct stuff.

Likewise, there could be a selfdestruct-like thing that would find EIP-6189 very useful, even if EIP-6190 isn’t implemented.

1 Like

EIP-6188’s behaviour with CREATE and CREATE2 is inconsistent with EIP-2681. The former allows the creation to proceed, but the latter does not.

Where does the 25 extra gas per hop come from? I’d expect it to cost at least as much as a call plus a storage read.

I think there’s an interesting attack here that needs some math to estimate. How much would it cost to get a self-destructed contract “close enough” to a not-yet-CREATE2’d contract to be able to use its storage?

25 gas in addition to the EIP-2929 costs.

Not sure. But I’m not sure how it would let it “use” its storage, if it simply forwards calls (after all, if it hasn’t been CREATE2’d yet, then it can’t really be called, so its storage can’t be modified this way).

What I’m imagining is: an attacker computes where the target contract will be deployed with CREATE2. Then they brute force where to deploy their malicious contract using The Price is Right rules (close but less than the target contract’s eventual address.) Then the malicious contract self-destructs multiple times to close the gap, eventually ending up where the target contract would’ve been deployed.

Then the malicious contract self-destructs multiple times to close the gap, eventually ending up where the target contract would’ve been deployed.

… causing the CREATE2 to either succeed, deploying the contract at a different address that the original address points to, or causing the CREATE2 to fail. I don’t see an issue here.

I could transfer ownership of a token to an address that hasn’t been created yet (perhaps I don’t want to reveal the implementation, or don’t want to pay for the deployment until I need to transfer the token again.) Someone could deploy other code to the same address.

Fair enough. I’ll calculate that.

As more and more contracts get selfdestructed sequentially, the gas cost for each selfdestruct increases linearly. So this attack will take polynomial gas as the number of hops increases.

Okay, so assuming that the attacker is willing to spend $E$ ether, with a gas price of $G$, then an upper bound for the maximum number of hops $n$ that the attacker can perform (ignoring the cost of creating the contracts and calling the function that selfdestructs) is given by:

$$\frac{10^9E}{G}=\frac{5000n(n+1)}{2}+\frac{100(n-1)n}{2}+2600n$$

Solving for the positive value of $n$:

$$n = \frac{1}{102}\frac{\sqrt{10201 G + 4080000000 E}}{\sqrt{G} - 101}$$

So using 100 ether with a gas cost of 20, the attacker could perform a maximum of 1,399 hops. Not counting the cost of deploying the contracts. But even the implausible 1,400x risk of an address collision is still safe due to the minuscule probabilities involved.

@SamWilsn do you have any other comments/concerns?

This is good content for the Security Considerations section.

The gas cost of SELFDESTRUCT is increased by 5000 for each alias contract that forwarded to the contract being self-destructed.

How is this calculated? Assume there are contracts at 0x5 and 0x6, then if I self-destruct the contract at 0x5, 0x5 becomes an alias contract for 0x7, correct? I then perform a CREATE2 and redeploy the contract at 0x5 (now stored at 0x7.) Finally I call the contract at 0x7 directly and cause it to self-destruct.

I don’t think this is functionally a problem since the next call into 0x5 will update the storage slot, but it does make me question:

Now that I think of it - why don’t I just point it to the contract that would be CREATE’d? This would avoid all of these issues by using something we already know to be secure.

Adding cancun-candidate tag.