So I have created an 'implementation contract' and a 'clone factory' which creates clones of the implementation contract. I have tested the functionality of the CloneFactory and it works in Remix.
However, I am now writing tests for the contract in Hardhat and it doesn't seem to be working correctly (Mocha and Chai). The issue I am facing is that the cloned contract is not being correctly initialised.
Here is my Clone Factory:
contract CloneFactory {
address public implementationContract;
address[] public allClones;
event NewClone(address indexed _instance);
mapping(address => address) public list;
constructor(address _implementation) {
implementationContract = _implementation;
}
function createClone(address _creator) payable external returns(address instance) {
instance = Clones.clone(implementationContract);
(bool success, ) = instance.call{value: msg.value}(abi.encodeWithSignature("initialize(address)", _creator));
allClones.push(instance);
list[_creator] = instance;
emit NewClone(instance);
return instance;
}
Here is the initialiser function in my Implementation Contract:
function initialize(address _creator) public initializer {
VRFConsumerBaseV2.initialise(vrfCoordinatorV2);
i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
creator = _creator;
Here is the test I am running (this is where I believe there is an issue):
it("Initialises contract correctly", async function () {
Main = await ethers.getContractFactory("Main");
main = await Main.deploy();
await main.deployed();
const dir = path.resolve(
__dirname,
"/Users/xxx/hardhat-smartcontract-main/artifacts/contracts/Main.sol/Main.json"
)
const file = fs.readFileSync(dir, "utf8")
const json = JSON.parse(file)
const abi = json.abi
CloneFactory = await ethers.getContractFactory("CloneFactory");
cf = await CloneFactory.deploy(main.address);
await cf.deployed();
let currentProvider = new web3.providers.HttpProvider('http://localhost:8545');
let web3Provider = new ethers.providers.Web3Provider(currentProvider);
const [addr1, addr2] = await ethers.getSigners();
const tx = await cf.createClone(addr1.address, {
value: ethers.utils.parseUnits("0", "ether")
});
const txReceipt = await tx.wait(1)
const cloneAddress = await txReceipt.events[0].args._instance
const clonedContract = new ethers.Contract(cloneAddress, abi, web3Provider)
const accountConnectedClone = clonedContract.connect(addr1)
const creator = await accountConnectedClone.getCreator()
expect(addr1.address).to.equal(creator)
})
When I run this test, I get the following output:
AssertionError: expected '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb…' to equal '0x00000000000000000000000000000000000…'
+ expected - actual
-0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
+0x0000000000000000000000000000000000000000
Basically, the creator is not being saved as the address of the caller of the 'createClone' function (which means it is not being initialized. I don't think there is an issue with the Clone Factory since this works correctly in Remix.
My suspicion is this has something to do with either the ABI or with the ethers/web3 provider, however I could be wrong.
There doesn't seem to be much info online about testing clone or proxy smart contracts so I hope someone here can help me out.
Thanks in advance!
EthereumBoy