0
pragma solidity >0.6.2 <0.7.0;

contract D {
    uint public x;
    constructor(uint a) public payable {
        x = a;
    }
}

contract C {

    address[] public addresses;
    address[] public predictedAddresses;
    // D d = new D(4); // will be executed as part of C's constructor

    function createD(uint arg) public {
        D newD = new D(arg);
        newD.x();
        addresses.push(address(newD));
    }

    function createAndEndowD(uint arg, uint amount) public payable {
        // Send ether along with the creation
        D newD = new D{value: amount}(arg);
        newD.x();
    }

    function createSalted(bytes32 salt, uint arg) public {

        address predictedAddress = address(bytes20(keccak256(abi.encodePacked(
            byte(0xff),
            address(this),
            salt,
            keccak256(abi.encodePacked(
                        type(D).creationCode,
                        arg
                        ))

        ))));

        D d = new D{salt: salt}(arg);
        require (address(d) == predictedAddress);

        predictedAddresses.push(predictedAddress);

    } 

}

Couldnt execute this transaction on Remix, Failed with this error

transact to C.createSalted pending ... 
[vm]from:0x7a0...9e160to:C.createSalted(bytes32,uint256) 0x9a6...ed3f2value:1332 weidata:0x611...00020logs:0hash:0x377...81188
transact to C.createSalted errored: VM error: revert.
revert  The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.  Debug the transaction to get more information. 
eth
  • 85,679
  • 53
  • 285
  • 406
GraphicalDot
  • 425
  • 4
  • 11
  • So how exactly does create2 fit in all of this? I don't see it even once in the body of your question, so can you please provide some more context on this? – goodvibration Apr 22 '20 at 13:56
  • https://ethereum.stackexchange.com/questions/79567/is-it-possible-to-deploy-a-contract-using-create2-in-solidity If you specify the option salt (a bytes32 value), then contract creation will use a different mechanism to come up with the address of the new contract: – GraphicalDot Apr 22 '20 at 13:59

1 Answers1

1

The problem is the convertion from bytes32 output from keccak256 to bytes20

address predictedAddress = address(bytes20(keccak256(...)));

It keeps the "leftmost" 20 bytes and you want the "rightmost" 20 bytes instead.

It can be fixed by shifting the bytes32 to the left 12 bytes = 96 bits before the conversion to bytes20:

address predictedAddress = address(bytes20(keccak256(...) << 96));
Ismael
  • 30,570
  • 21
  • 53
  • 96