How to initialize value of minimal proxy contract(EIP1167 "constructor")?

The question is after deploying the clone contract (Openzeppelin clone https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/Clones.sol)

How should one initialize the values? If i understand correctly, Instead of constructor we must replace it with a function that initializes the value

Is there a way to create the contract & execute the function at the same time?

Or do i have to do it like this

address _clone = clone(contractToBeCloned);
ContractToBeCloned(_clone).myfunction(argument)

Is there a better way?

I don't believe there is a better way, you clone the contract and then call your initialize(...) function
ContractToBeCloned(_cline).initialize(... your params ...);

(assuming you're also using @openzeppelin/contracts/proxy/utils/Initializable.sol )

The way the EIP 1167 clone deployment works prevents you from passing any other data.

--

Alternatively what people do is create an Factory Contract with a function to create the clone and then call their init function the same function call.

Hello :smiley:

Related question, does a constructor MUST be implemented in the master contract? I.e. I've seen master contracts implementing an empty constructor like this

// solhint-disable-next-line no-empty-blocks
constructor() {}

I don't understand why an empty constructor is needed. As far as I understand it is only needed for pre-initializing common parameters before clones are deployed.

Be sure that the master contract is pre-initialized. You can usually accomplish this in your constructor as the only time the master contract constructor is called is during the master contract's creation. - https://github.com/optionality/clone-factory

I.e. what if I don't need to pre-initialize the master copy!

Thank you in advance,
Cosimo

Yes, you are correct that when using the Clones contract from the OpenZeppelin library, you will need to use a separate function to initialize the values of the clone contract rather than a constructor.

To create the contract and execute the function at the same time, you can use the new keyword and pass in the arguments for the function as part of the contract deployment.

Example of how you could do this:

pragma solidity ^0.7.0;

import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/proxy/Clones.sol";

contract MyContract {
    // Declare the contract that you want to clone
    MyContractToBeCloned contractToBeCloned;

    function deployAndInitialize(address _contractToBeCloned) public {
        // Deploy the clone contract
        address clone = new Clones(_contractToBeCloned);

        // Initialize the values of the clone contract
        MyContractToBeCloned(_clone).initialize(/* arguments for initialize function */);
    }
}

Alternatively, you can also use the create2 function to create and deploy the clone contract, and then call the initialization function separately.

pragma solidity ^0.7.0;

import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/proxy/Clones.sol";

contract MyContract {
    // Declare the contract that you want to clone
    MyContractToBeCloned contractToBeCloned;

    function deploy(address _contractToBeCloned) public {
        // Deploy the clone contract
        address clone = Clones.create2(_contractToBeCloned, /* salt */);

        // Initialize the values of the clone contract
        MyContractToBeCloned(_clone).initialize(/* arguments for initialize function */);
    }
}