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. 
2
  • 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? Apr 22 '20 at 13:56
  • ethereum.stackexchange.com/questions/79567/… 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: Apr 22 '20 at 13:59
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));
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.