This conversation has been great!
I'd like to build on the pattern you laid out above with MyTokenFactoryBeacon
, but rather than hard-code MyTokenUpgradeable
in the constructor, use simply an implementation
address that could point to anything that was upgradeable. Ultimately, this would be a reusable factory, regardless of what the implementation is. One could imagine its implementation to look something like:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
contract ProxyBeaconFactory {
address public beacon;
address[] public beacons;
event ProxyDeployed(address proxyAddress);
constructor(address implementation_) {
UpgradeableBeacon _beacon = new UpgradeableBeacon(
implementation_
);
_beacon.transferOwnership(msg.sender);
beacon = address(_beacon);
}
function create(bytes calldata data) external returns (address) {
address proxyAddress = new BeaconProxy(beacon, data);
beacons.push(proxyAddress);
emit ProxyDeployed(proxyAddress);
return proxyAddress;
}
}
I do wonder though about the recent announcement regarding potential risks using UUPS. If the implementation_
does indeed implement the UUPS pattern, are there any measures that need to be taken to guard against those risks?
Additionally, I believe the pattern to ultimately use this is something like:
1. Deploy a MyTokenUpgradeable contract normally - without OZ upgrades or anything.
2. Deploy ProxyBeaconFactory(myTokenUpgradeable.address)
3. proxyBeaconFactory.create(dataToInitializeAnInstanceOfMyTokenUpgradeable)
Am I thinking about this the right way?