5

In my project I'm using an EIP-1167-enabled Clone Factory:

function createClone(address target) external returns (address result) {
    bytes20 targetBytes = bytes20(target);
    assembly {
      let clone := mload(0x40)
      mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
      mstore(add(clone, 0x14), targetBytes)
      mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
      result := create(0, clone, 0x37)
    }
    addr = result;
}

It works for contracts without constructor or contracts with empty constructors.

Here is a constructor for most of my contracts:

constructor(
    bytes32 pRegistryGroupName,
    bytes32 pRegistryName
)
    internal
{
    m_RegistrableData.registryGroupName = pRegistryGroupName;
    m_RegistrableData.registryName = pRegistryName;
}

When I clone my contract, as expected, the new one doesn't contain group name nor name.

I would like to have it like:

function createClone(address target, bytes32 groupName, bytes32 name)

How can I do that?

Also I'm curious what are these addresses and what they represent, why they look like that:

  • 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
  • 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
1

1 Answer 1

5

We solved this by having a one time init function. For full source, see ThingFactory.sol and Thing.sol. Basically, what you do is have this one time init function on your target contract (in the example, it would be Thing.) Then your factory contract calls the init function directly after creating the clone.

The 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 and 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 are the standardized bytecode template of EIP-1167. The first 0x3d602d80600a3d3981f3 of the first section is the constructor of the clone contract, which is static and just returns the bytecode from said EIP.

Source: I'm one of the developers of clone-factory and EIP-1167

1
  • 2
    I guess that instead of coding a one-time init function from scratch, one could also import and use OpenZeppelin's battle-tested Initializable.sol. Sep 7, 2021 at 10:30

Your Answer

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

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