2

I am trying to get the bytecode from a deployed contract, then by using that bytecode, use the CREATE opcode to deploy a new instance of that contract.

Here is the code I'm trying out (but to no avail)

Implementation contract (already deployed) :

contract Implementation {
   address public owner;

   constructor(address _owner) {
      owner = _owner;
   }
}

Deployer contract :

contract Deployer {

   address public implementation;

   constructor(address _implementation) {
      implementation = _implementation;
   }

   function deployContract() public returns (address deployed) {
      bytes memory bytecode = abi.encodePacked(implementation.code, abi.encode(msg.sender));
      assembly{
            deployed := create(0, add(bytecode, 0x20), mload(bytecode))
            if iszero(extcodesize(deployed)) {
                revert(0, 0)
            }
      }
   }

After deploying both contracts (Implementation contract first) then setting the Implementation contract as the address public implementation on the deployer contract, calling deployContract() will always revert.

Any pointers would be much appreciated.

1 Answer 1

2

Update :

I was able to work through this problem. Unfortunately there is no way to get the creation bytecode from a deployed address. You can get it from type(ContractName).creationCode, but that requires that your contract has the code available. To work through this problem I had to change the address implementation to bytes implementation and set it as the creationCode (there are numerous ways to get this, and the information is widely available). Then I was able to use that bytecode + the constructor parameters and the instance was created.

EDIT : Here is the code (confirmed to be working)

contract Deployer {

   bytes public implementation;

   constructor(bytes _implementation) {
      implementation = _implementation;
   }

   function deployContract() public returns (address deployed) {
      bytes memory bytecode = abi.encodePacked(implementation, abi.encode(msg.sender));
      assembly{
            deployed := create(0, add(bytecode, 0x20), mload(bytecode))
            if iszero(extcodesize(deployed)) {
                revert(0, 0)
            }
      }
   }

   function changeImplementation(bytes memory _implementation) public {
      implementation = _implementation;
   }

By going with this method, I am able to change the implementation by calling the changeImplementation(bytes memory _implementation) function. The method I used to get the creation bytecode was by compiling the implementation contract and going in the artifacts folder (truffle or hardhat), the byteCode will be in the json file for the implementation contract (near the end of the json file). By setting the bytes public implementation as the bytecode, you will be able to change the implementation whenever you need to, making this a modular way to set up a 'Deployer' contract.

2
  • 1
    Welcome to the Ethereum Stack Exchange and thanks for self-answering. Though "the information is widely available" it would probably still be helpful for people if you are able to include the code you chose.
    – eth
    Jun 24, 2023 at 3:55
  • 1
    Hello eth, I have edited my answer to show how I went about solving the problem. Thanks
    – Allan
    Jun 24, 2023 at 5:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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