Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
eggy-eth opened this issue Oct 10, 2018 · 2 comments

Comments

@eggy-eth
Copy link

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.

@holiman
Copy link
Contributor

holiman commented Oct 10, 2018

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

Nope, the EIP reads:

Specifically, if nonce or code is nonzero, then the create-operation fails.

If a create-operation succeeds, the new address will be returned on the top of the stack. If you get a 0 on the top of the stack, the create has failed. Which seems to be exactly what happened: " Last is now 0x0."

@ElKornacio
Copy link

@holiman I think it is quite reasonable to state this in the EIP more explicitly. Right now, EIP-684 says:

... the destination address already has either nonzero nonce, or nonempty code, then the creation throws immediately

And EIP-1014 says: "The behaviour at collisions is specified by EIP-684". And even quotes the line above.

So it doesn't feel obvious that after the words "throws immediately", the phase "the create-operation fails" means "zero on top of the stack".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants