Potential security implications of CREATE2? (EIP-1014)

Gladly. It goes like this:

  • Company XYZ: Announcing the $50MM Ethereum killer app!

  • Ethereum community: Killer App! But wait a tick; you forgot to guard against CREATE2 exploits

  • Company XYZ: Ah, shoot, you’re right. Well, it would be cost prohibitive to redo it now; You’ll just have to trust us

  • Ethereum community: Okie dokie, then.

  • (months or years pass)

  • Company XYZ: Ooops! Turns out I was a scoundrel. Contract replaced. Money stolen, or whatever I want.

Eliminating the double negatives, you want me to prove redeployments are possible? Your very own CREATE2 does that, friend.

OK, I’m going to stop beating this dead horse because it’s getting me nowhere. I’ll just reiterate this:

People don’t trust the network because they verified some bytecode. That is not how the real world works. People trust the network because a lot of horrible shit that could’ve happened didn’t. That’s it.

This is inviting another DAO-like disaster. You really think we’ll get away with it twice?

I’ve gone ahead and implemented a factory contract for creating what I’m calling metamorphic contracts, or contracts that can be redeployed with new bytecode to the same address. It does so by first deploying an implementation contract, then deploying a transient contract with fixed, non-deterministic initialization code via CREATE2. The transient contract clones the bytecode of the implementation contract and uses it to deploy the metamorphic contract via CREATE, then immediately self-destructs. There’s also an immutable create2 factory contract for preventing metamorphism in any contracts it deploys, which operates similarly to the one by @jochem-brouwer, but with a different mechanism for preventing address collisions / frontrunning.

Use this feature / bug responsibly, try to educate as many people as possible, and stay vigilant against mutable villainy!

4 Likes

Revised the metamorphic contract factory so that it no longer requires an intermediate transient contract. Here’s an explanation of the current initialization code used to deploy the metamorphic contracts: https://gist.github.com/0age/9a4541cce380a1b2c7e477af06ba6376

Here’s another use-case for metamorphic contracts: you can use their runtime code as dynamic storage to save gas in certain applications https://medium.com/coinmonks/on-efficient-ethereum-storage-c76869591add

I’ve updated my own written material about EIP-1014 to reflect Rajeev’s (and this thread’s) concerns about the proposal. Ethereum’s EIP 1014: CREATE2. Counterfactual Interactions with… | by Tim Cotten | Cotten.IO

Until I read this thread I had not realized how trivial EIP-1014 made it to create mutable contracts, but can now fully grasp the attack vectors described and the danger of doing this. I strongly agree with those who say we can’t rely on external block explorers for safety: this is an on-chain problem.

pereztechseattle This is inviting another DAO-like disaster. You really think we’ll get away with it twice?

Bleh. Does an EIP not exist for determining whether an address contains a contract or not? I’ve seen the code relying on EXTCODESIZE but as has been pointed out can be hacked when being checked within a constructor (https://ethereum.stackexchange.com/questions/15641/how-does-a-contract-find-out-if-another-address-is-a-contract/64340#64340).

It’d be nice to have an OPCODE that can definitely state: Account, Contract (CREATE), Contract (CREATE2).

1 Like

Following along with https://medium.com/coinmonks/why-create2-e99b6afcc28c there’s some really interesting work about the ability to replicate the utility of CREATE2 with standard CREATE.

I just released an article on another application for redeployable contracts - using them to create a wallet contract, or “home address”, that supports repeated deployment of arbitrary “transaction scripts” (and a utility for working with home addresses called HomeWork): https://medium.com/@0age/on-efficient-ethereum-transactions-introducing-homework-6ae4f21801ed

How to generate different contract bytecode in the same address? if the address is the same, so the init_code must be the same, and then the bytecode is the same(without using delegatecall and so on), so can you give a solidity example to generate different contract bytecode in the same address JUST using create2 ? it confuses me a lot of time. anyone can help me ? thank you very much !

How to generate different contract bytecode in the same address? if the address is the same, so the init_code must be the same, and then the bytecode is the same(without using delegatecall and so on), so can you give a solidity example to generate different contract bytecode in the same address JUST using create2 ? it confuses me a lot of time. anyone can help me ? thank you very much !

If delegatecall proxies such as USDC and TUSD were replaced by CREATE2 reincarnations, it would reduce the call overhead of upgradeable contracts by at least 1500 gas.

So after 4.5 years, how much has been lost due to cases of malicious occurences related to CREATE2?

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

contract Beacon {
    address public logic;
    
    function setLogic(address _logic) external {
        logic = _logic;
    }
}

contract Clone {
    constructor(address _beacon) {
        address logic = Beacon(_beacon).logic();
        bytes memory code = logic.code;
        assembly {
            return (add(code, 0x20), mload(code))
        }
    }
}