1

I have a contract which deploys other contracts by bytecode:

contract DeployContract {
    function deploy(bytes calldata _bytecode) external returns(address addr) {

        bytes memory bytecode = abi.encode(_bytecode, msg.sender);
        assembly {
            addr := create(0, add(bytecode, 0x20), mload(bytecode))
            if iszero(extcodesize(addr)) {
                revert(0, 0)
            }
        }
    }
}

I want to deploy contracts which take an address as argument in their constructor. Appending the address to the bytecode as above does not work. How do I pass the constructor parameter?

  • 1
    You need to abi-encode them, and then append the result at the end of the bytecode, before passing it to the create function. – goodvibration Jan 5 at 18:52
2

You need to abi-encode the input arguments, and then append the result at the end of the bytecode before passing it to the create function.

Suppose you have input arguments arg1, arg2 and arg3.

I believe that you can more or less achieve that by changing this:

bytes memory bytecode = _bytecode;

To this:

bytes memory bytecode = abi.encode(_bytecode, arg1, arg2, arg3);

I haven't tested it, so feel free to do it and report back...

| improve this answer | |
  • I tested it and it didn't work for me. Maybe there is something wrong with how I am giving the bytecode to the create instruction – Bobface Jan 5 at 19:17
  • I have researched a bit more and changed the code a little bit. I have edited my original question with the new code. It still does not work unfortunately. – Bobface Jan 5 at 19:48
2

This worked for CREATE2. Maybe it also works on CREATE?

abi.encodePacked(bytecode, abi.encode(arg1, arg2))

Example (CREATE2)

pragma solidity ^0.5.11;

contract Wallet {
    address public owner;
    uint public foo;

    constructor(address _owner, uint _foo) public {
        owner = _owner;
        foo = _foo;
    }
}

contract Factory {
    event Deployed(address addr, uint256 salt);

    function getCreationBytecode(address _owner, uint _foo) public pure returns (bytes memory) {
        bytes memory bytecode = type(Wallet).creationCode;

        return abi.encodePacked(bytecode, abi.encode(_owner, _foo));
    }

    // NOTE: call this function with bytecode from getCreationByteCode and a random salt
    function deploy(bytes memory bytecode, uint _salt) public {
        address addr;
        assembly {
            addr := create2(0, add(bytecode, 0x20), mload(bytecode), _salt)

            if iszero(extcodesize(addr)) {
                revert(0, 0)
            }
        }

        emit Deployed(addr, _salt);
    }
}
| improve this answer | |
0

You have to encode arguments with abi.encode and bytes with abi.encodePacked. Compiles with Solidity 0.4.0.

contract DeployContract {
    function deploy(bytes  _bytecode) external returns(address addr) {

        bytes memory bytecode = abi.encodePacked(_bytecode, abi.encode(msg.sender));
        assembly {
            addr := create(0, add(bytecode, 0x20), mload(bytecode))
            if iszero(extcodesize(addr)) {
                revert(0, 0)
            }
        }
    }
}
| improve this answer | |

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.