I am trying to build an implementation of ProxyFactory. I am taking inspiration from the endaoment-contracts here. They have used a ProxyFactory which creates minimal proxies.
The issue I am facing is that my implementation creates the same Factory contract instead of the proxy contract.
import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol";
contract ProxyFactory {
event ProxyCreated(address proxy);
function deployMinimal(address _logic, bytes memory _data) public returns (address proxy) {
// Adapted from https://github.com/optionality/clone-factory/blob/32782f82dfc5a00d103a7e61a17a5dedbd1e8e9d/contracts/CloneFactory.sol
bytes20 targetBytes = bytes20(_logic);
assembly {
let clone := mload(0x40)
mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(clone, 0x14), targetBytes)
mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
proxy := create(0, clone, 0x37)
}
emit ProxyCreated(address(proxy));
if(_data.length > 0) {
(bool success,) = proxy.call(_data);
require(success);
}
}
}
My Box Contract is
// SPDX-License-Identifier: MIT
pragma solidity 0.8.3;
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract BoxV2 is UUPSUpgradeable {
address public owner;
uint256 public length;
uint256 public width;
uint256 public height;
function initialize(uint256 l, uint256 w, uint256 h) public initializer {
owner = msg.sender;
length = l;
width = w;
height = h;
}
function volume() view public returns (uint256) {
return length * width * height;
}
function _authorizeUpgrade(address newImplementation) internal override virtual {
require(msg.sender == owner, "Unauthorized Upgrade");
}
}
And my BoxFactory contract is
import "@openzeppelin/contracts-upgradeable/utils/Create2Upgradeable.sol";
import "./ProxyFactory.sol";
contract BoxFactory is ProxyFactory{
event BoxCreated(address proxy);
address[] public proxies;
address public _logic;
constructor (address logic) {
_logic = logic;
}
function createByDeployingMinimal(uint256 l, uint256 w, uint256 h) public returns (address){
bytes memory payload = abi.encodeWithSignature(
"initialize(uint256,uint256,uint256)",
l,
w,
h
);
address proxy = deployMinimal(_logic, payload);
emit BoxCreated(proxy);
proxies.push(proxy);
return proxy;
}
}
I’m using Remix-IDE and I am doing the following steps
- Deploying the
BoxV2contract and note down its address - Deploy a
BoxFactoryusing the address above as the_logicparameter. - I can see that there is a new Contract created. When I take the address (from emitted logs) and paste it in the Remix’s “At Address” textbox, it shows me another instance of
BoxFactory. I am expecting to see either a Proxy contract or the BoxV2 contract. Is that incorrect?
Regards,