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;
}