Thanks a lot @ericglau .. For anybody interested in how i went about this eventually. I used an hybrid solution.. I deployed a beacon and implementation using deployBeacon, but i wanted an on-chain solution for the factory. So my factory ended up looking like this
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.6;
import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
import "./BoxV1.sol";
contract BoxFactory {
address private immutable boxBeacon;
mapping(uint32 => address) private boxes;
event BoxDeployed(address tokenAddress);
constructor(address _boxBeacon) {
boxBeacon = address(_boxBeacon);
}
function buildBox(
uint256 _age,
string calldata _name,
uint32 _boxId
) external returns (address) {
BeaconProxy proxy = new BeaconProxy(
boxBeacon,
abi.encodeWithSelector(BoxV1.initialize.selector, _age, _name)
);
boxes[_boxId] = address(proxy);
emit BoxDeployed(address(proxy));
return address(proxy);
}
function getBoxByIndex(uint32 index) external view returns (address) {
return boxes[index];
}
}
I'm taking the beacon from using deployBeacon and passing its address to the factory.
const BoxFactory = await ethers.getContractFactory(
"BoxFactory",
contractOwner
);
bfactory = await BoxFactory.deploy(beacon.address);
await bfactory.deployed();
console.log("factory deployed to:", bfactory.address);
await (await bfactory.buildBox(21, "SomeName", 1)).wait();