0

Hi Devs

I'm in the middle of a professional project & facing a small issue. Your help will sincerely appreciated

I deployed the upgradeable contract below using UpgradeableBeacon and hardhat-deploy. The deployment is fine to some extend, can read methods/functions from contract except for two essential functions 1- owner & 2- implementation address.

I modified upgradeableBeacon constructor to initilaize function so Factory can inherit it. nothing major.

what I did to troubleshot this problem:

I tried using getContractAt using deployments, contract abi, & address. getContractAt using contract name and deployer address. & using getContract. same results everytime

UpgradeableBeacon Contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/proxy/beacon/IBeacon.sol';
import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';

contract UpgradeableBeacon is Initializable, IBeacon, OwnableUpgradeable {
    address private _implementation;

    event Upgraded(address indexed implementation);

    function __UpgradeableBeacon_init(address implementation_) public virtual onlyInitializing{
        __Ownable_init();
        _setImplementation(implementation_);
    }

    function implementation() public view virtual override returns (address) {
        return _implementation;
    }

    function upgradeTo(address newImplementation) public virtual onlyOwner {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    function _setImplementation(address newImplementation) private {
        require(AddressUpgradeable.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract");
        _implementation = newImplementation;
    }
}

Factory Contract

//SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;

import '@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol';
import '@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol';
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';
import './interfaces/IFactory.sol';
import './interfaces/IDTokenInterface.sol';
import './proxy/UpgradeableBeacon.sol';



contract Factory is Initializable, IRealtyFactory,PausableUpgradeable, UpgradeableBeacon {


  IDTokenInterface private ID;


  function __Factory_init(address idContract, address impl) public virtual initializer {
    __Pausable_init();
    __UpgradeableBeacon_init(impl);

    ID = IDTokenInterface(idContract);
  }
}

Deployment Script using hardhat-deploy

const { ethers, network } = require('hardhat')

module.exports = async({getNamedAccounts, deployments}) => {
    const { deploy, log, get } = deployments;
    const { deployer } = await getNamedAccounts();
    // console.log({namedAccounts: await getNamedAccounts()})

    const networkName = network.name
    const idToken = await get('IDToken')
    // console.log(`IDToken Contract address is ${idToken.address}`)

    const implementation = await deploy('BitRealty', {
        contract: 'BitRealty',
        args:[],
        log: true,
        from: deployer,
        waitConfirmations: network.config.blockConfirmations || 1
    })

    const deployedImp = await ethers.getContractAt('BitRealty', implementation.address)


    const factory = await deploy('Factory', {
        contract: 'Factory',
        from: deployer,
        args:[],
        log: true,
        execute: {
            methodName: '__Factory_init',
            args:[idToken.address, implementation.address]
        },
        waitConfirmations: network.config.blockConfirmations || 1
    })
    const tryFactory = await deployments.get('Factory')
    const deployedFactory = await ethers.getContractAt(tryFactory.abi, tryFactory.address)

    console.log(`Deployed Implementation Address:  ${implementation.address}`)
    console.log(`Deployed Factory Address:  ${factory.address}`)
    console.log(`Deployer: ${deployer}`)
    console.log(`Factory Owner from Factory:  ${await deployedFactory.owner()}`)
    console.log(`Implementation Address from Factory:  ${await deployedFactory.implementation()}`)
    console.log(`Is Factory Paused:  ${await deployedFactory.isPaused()}`)

}
module.exports.tags = ['all']

And Finally this is the output of console.log reading factory functions: Error 1: owner should deployer but its address zero Error2: implementation address is address zero

deploying "BitRealty" (tx: 0x0997482ff562049e8200a04d77438f96372d63b5d764caa0b0e57086b4ecb6a8)...: deployed at 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9 with 2257315 gas
deploying "Factory" (tx: 0xd2e12dfe86fe9d61eb5bc3f3b0ff5f26671c185acfc9c49044fe7f2ddbe398f0)...: deployed at 0x5FC8d32690cc91D4c39d9d3abcBD16989F875707 with 2675360 gas
Deployed Implementation Address:  0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9
Deployed Factory Address:  0x5FC8d32690cc91D4c39d9d3abcBD16989F875707
Deployer: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Factory Owner from Factory:  0x0000000000000000000000000000000000000000
Implementation Address from Factory:  0x0000000000000000000000000000000000000000
Is Factory Paused:  false

1 Answer 1

1

In your Factory Contract.sol file the initialisation function of the factory is called __Factory_init where as when deploying the contract you are calling the __RealtyFactory_init. Do you see it?
The line where you deploy the factory:

const factory = await deploy('Factory', {
        contract: 'Factory',
        from: deployer,
        args:[],
        log: true,
        execute: {
            methodName: '__RealtyFactory_init',
            args:[idToken.address, implementation.address]
        },
        waitConfirmations: network.config.blockConfirmations || 1
    })

Should be as follows:

const factory = await deploy('Factory', {
        contract: 'Factory',
        from: deployer,
        args:[],
        log: true,
        execute: {
            methodName: '__Factory_init',
            args:[idToken.address, implementation.address]
        },
        waitConfirmations: network.config.blockConfirmations || 1
    })
1
  • Thanks Hristo for your response, Originally the contract name is RealtyFactory but I changed here in the question as the project is really big, I will correct it here. but if you look at the console log you will see I can read contract functions except for 2 mentioned above!!
    – sasha
    Commented Mar 20, 2023 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.