I have a base contract that inherits from Initializable
. I have a derived contract that inherits from Initializable
and BaseContract
. I'd like to be able to deploy the derived contract as clones, and initialize variables in both the derived and base contract initializers.
I know that I can't call super.initialize()
in the derived contract because the transaction will revert (since initialize can only be called once). I'd like a way to pass parameters to the base contract initializer. How can I best achieve this? Here's a small reproducible example:
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
contract BaseExample is Initializable {
string public setInBase;
constructor() initializer {}
function initialize(string calldata _initData) public initializer {
setInBase = _initData;
}
}
contract Derived is Initializable, BaseExample {
string public setAfterInit;
function initialize(
string calldata _initData,
string calldata _baseInitData
) external initializer {
setAfterInit = _initData;
// can I initialize setInBase somehow here?
// I want to pass _baseInitData to the base contract initializer as a parameter
}
}
contract FactoryExample {
address public implementation;
constructor(address _implementation) {
implementation = _implementation;
}
event DerivedCreated(address indexed derived);
function createDerived(string calldata initData) external returns (address) {
address derived = Clones.clone(implementation);
(bool success, ) = derived.call(
abi.encodeWithSignature(
"initialize(string,string)",
initData,
"base init data" // just making this static so we can see if it works
)
);
if (!success) {
// if I were to call super.initialize() in my Derived, this will happen!
revert("Failed to create a derived!");
}
emit DerivedCreated(derived);
return derived;
}