@frangio
I'm using hardhat to do some testing. I had built an upgradeable contract using uups. All works as expected by itself. I am now attempting to deploy that contract using BeaconProxy factory and an UpgradeableBeacon. I have removed the UUPS logic from the implementation contract. (removed UUPSUpgradeable library and removed the _authorizeUpgrade function. Similar to what @0xLostArchitect was saying on Oct. 22 post.)
So, long story short: The initial implementation deploys fine. The factory and beacon contracts deploy fine. I then call the factory function to create a new proxy, that seems to work too. However, when I try to call a function from that new proxy I receive a "Error: call revert exception". Here is my code (bare minimum on the implementation contract):
GolfEventBeacon.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract GolfEventBeacon is Ownable {
UpgradeableBeacon immutable beacon;
address public golfEventBlueprint;
constructor(address _initBlueprint) {
beacon = new UpgradeableBeacon(_initBlueprint);
golfEventBlueprint = _initBlueprint;
transferOwnership(tx.origin);
}
function update(address _newBlueprint) public onlyOwner {
beacon.upgradeTo(_newBlueprint);
golfEventBlueprint = _newBlueprint;
}
function implementation() public view returns (address) {
return beacon.implementation();
}
}
GolfEventFactory.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "hardhat/console.sol";
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
import "./GolfEventBeacon.sol";
import "./GolfEvent.sol";
contract GolfEventFactory {
mapping(uint32 => address) private events;
GolfEventBeacon immutable beacon;
constructor(address _initBlueprint){
beacon = new GolfEventBeacon(_initBlueprint);
}
function createGolfEvent(
string calldata _eventSetName,
string calldata _eventSetSymbol,
uint32 eventId
) external {
BeaconProxy golfEvent = new BeaconProxy(address(beacon),
abi.encodeWithSelector(GolfEvent(address(0)).initialize.selector, _eventSetName, _eventSetSymbol));
events[eventId] = address(golfEvent);
}
function getEventAddress(uint32 eventId) external view returns (address) {
return events[eventId];
}
function getBeaconAddress() public view returns (address) {
return address(beacon);
}
}
GolfEvent.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import "hardhat/console.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol";
contract GolfEvent is Initializable, OwnableUpgradeable, ERC721URIStorageUpgradeable {
function initialize(string memory _eventSetName, string memory _eventSetSymbol) payable external initializer{
__Ownable_init();
__ERC721_init(_eventSetName, _eventSetSymbol);
console.log("%s name service deployed. Symbol: %s", _eventSetName, _eventSetSymbol);
}
//simple function to print out version
function getVersion() pure public virtual returns (string memory) {
return "GolfEvent_v1!";
}
}
finally my run.js
const main = async () => {
// The first return is the deployer, the second is a random account
const [owner, superCoder] = await hre.ethers.getSigners();
// deploy original implementation contract
const v1ContractFactory = await hre.ethers.getContractFactory('GolfEvent');
const v1Contract = await hre.upgrades.deployProxy(v1ContractFactory,
["pitty", "pty"]);
await v1Contract.deployed();
console.log("Initial Golf Event Contract deployed to: ", v1Contract.address);
// Deploy the beaconproxy factory
const factoryFactory = await hre.ethers.getContractFactory('GolfEventFactory');
const factoryContract = await factoryFactory.deploy(v1Contract.address);
await factoryContract.deployed();
console.log("Factory Contract deployed to:", factoryContract.address);
// Get becon contract address that was deployed automatically by the factory contract
const beaconContract = await hre.ethers.getContractAt("GolfEventBeacon", await factoryContract.getBeaconAddress());
console.log("beaconContract address: ", beaconContract.address);
// Create first golf event proxy and get that address
await factoryContract.createGolfEvent("FirstEvent","FEV",1);
const firstEventContract = await hre.ethers.getContractAt("GolfEvent",await factoryContract.getEventAddress(1));
console.log("First golf event address: ",firstEventContract.address);
// call the getVersion function of the new proxy (THIS FAILS)
const versionResult = await firstEventContract.getVersion();
console.log("first golf event contract version: ", versionResult);
}
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
Using hardhat I run:
npx hardhat run scripts/run.js
and receive this exception:
Error: call revert exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ]
(method="getVersion()", data="0x", errorArgs=null, errorName=null, errorSignature=null,
reason=null, code=CALL_EXCEPTION, version=abi/5.6.1)
{
reason: null,
code: 'CALL_EXCEPTION',
method: 'getVersion()',
data: '0x',
errorArgs: null,
errorName: null,
errorSignature: null,
address: '0x6D544390Eb535d61e196c87d6B9c80dCD8628Acd',
args: [],
transaction: {
data: '0x0d8e6e2c',
to: '0x6D544390Eb535d61e196c87d6B9c80dCD8628Acd',
from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
gasLimit: BigNumber { value: "29021272" }
}
}
Any thoughts on what I could be doing wrong? Thanks!