Skip to content

CREATE2 can be ran twice creating code at the same address instead of reverting (no storage is changed) #17881

@eggy-eth

Description

@eggy-eth

System information

Geth version: Version: 1.8.17-stable
OS & Version: OSX

Expected behaviour

CREATE2 reverts tx if a contract is tried to be deployed twice at the same address

Actual behaviour

Does not revert. Uses more gas than in the initial creation. For some reason does not alter the storage even though there is a check to see if the storage is altered. Does return address 0x0 on the second create.

Steps to reproduce the behaviour

  1. Deploy the TestMe contract
  2. Call Deploy with any seed and set argument to any value.
  3. Verify that the contract A is created at the address which can be found in Last (CurrVal should be same as argument)
  4. Now redeploy TestMe: use the same seed but a different argument
  5. The code now re-runs, does not revert. Last is now 0x0. The CurrVal in A does not change.
contract TestMe{
    
    address public Last;
    
    uint public Argument;
    
    function Deploy(uint seed, uint arg) public returns (address) {
        Argument = arg;
        // ctr is the actual runtime bytecode of contract A 
        // compiled with 0.5.0-nightly.2018.10.9+commit.4ab2e03b.Emscripten.clang in remix
        bytes memory ctr = hex'608060405234801561001057600080fd5b50600033905080600160a060020a0316631543b3136040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b15801561006b57600080fd5b505afa15801561007f573d6000803e3d6000fd5b505050506040513d602081101561009557600080fd5b5051600055506099806100a96000396000f3fe608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f1aab64181146043575b600080fd5b348015604e57600080fd5b5060556067565b60408051918252519081900360200190f35b6000548156fea165627a7a723058205665d5eb639b7be5314a60862785a6b2285a4de4f2a382d6f5aa4ddf8917e9570029';
        address a;
        assembly{
            let pointer := ctr
            let len := mload(pointer)
            let start := add(pointer, 0x20)
            a := create2(0, start, len, seed)
        }
        Last = a;
        return (a);
    }
}

contract A{
    uint public CurrVal;
    constructor() public {
        TestMe target = TestMe(msg.sender);
        CurrVal = target.Argument();
    }
}

Note: you cannot pass "argument" in the constructor because this changes the init_code.

By EIP 1014 create2 at an address which has already code OR a nonce it should revert.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions