Deploy ERC20Upgradeable without Proxy for governable upgrades

Basically, I'm trying to deploy an upgradable token implementation without the proxy. I have a proxy deployed already, and I would like to update the implementation using governance. I've created an UUPS upgrade able token (minified for the example)

    contract GovernanceToken is Initializable, ERC20Upgradeable, ERC20PermitUpgradeable, ERC20VotesUpgradeable, OwnableUpgradeable, UUPSUpgradeable {
        /// @custom:oz-upgrades-unsafe-allow constructor
        constructor() {
            _disableInitializers();
        }
    
        function initialize() initializer public {
            __ERC20_init("GovernanceToken", "GT");
            __ERC20Permit_init("GovernanceToken");
            __ERC20Votes_init();
            __Ownable_init();
            __UUPSUpgradeable_init();
        }
    
        //...
    }

My deploy script looks like this:

    const deployGovernanceToken: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
      // @ts-ignore
      const { getNamedAccounts, deployments, network } = hre
      const { deploy, save, log, get } = deployments
      const { deployer } = await getNamedAccounts()

      const governanceTokenContractFactory = await ethers.getContractFactory(GOVERNANCE_TOKEN_NAME);
      
      const deployedProxy = await upgrades.deployProxy(governanceTokenContractFactory, [], {
        initializer: "initialize",
        kind: "uups",
      });

      await deployedProxy.deployed();
        
      const governanceToken = await governanceTokenContractFactory.attach(
          deployedProxy.address
      );

      const timeLock = await get(TIMELOCK_CONTROLLER_NAME)
      const governanceTokenContract = await ethers.getContractAt(GOVERNANCE_TOKEN_NAME, governanceToken.address)

      const transferTx = await governanceTokenContract.transferOwnership(timeLock.address)
      await transferTx.wait(1)
    }

I would like to upgrade my token, however it's owned by the timelock so I cannot upgrade it from hardhat, so I'd like to deploy another version of the token so I can upgrade it though governance.

This is my upgrade script:

    const { getNamedAccounts, deployments, network } = hre
    const { deploy, log } = deployments
    const { deployer } = await getNamedAccounts()
    const timelockAddress = '0x...'
    
    const governanceTokenV2 = await ethers.getContractFactory(GOVERNANCE_TOKEN_NAME);
    const governanceTokenContract = await governanceTokenV2.deploy();
    
    log(`Upgraded Token at ${governanceTokenContract.address}`)

//       

    const owner = await governanceTokenContract.owner();
    log(`Verified Token at ${governanceTokenContract.address}`)
    log(`owner: ${owner}`)

When I run this I get an error:

Deploying governanceToken and waiting for confirmations...
Upgraded Token at 0x5Fb...
owner: 0x0000000000000000000000000000000000000000

Error HH604: Error running JSON-RPC server: ERROR processing C:..\deploy\00-deploy-upgraded-Token.ts:
Error: VM Exception while processing transaction: reverted with reason string 'Ownable: caller is not the owner'

The token I'm deploying claims the owner is the ZERO_ADDRESS, perhaps this is because the storage is usually associated with the proxy?

How can I deploy this token and transfer ownership to the proxy?

**Note: ** I've also tried calling initialize directly after deployment and I get an error:

reason="execution reverted: Initializable: contract is already initialized"

Hi, welcome to the community! :wave:

I think you should call initialize() to claim the ownership.

When I call initialize it claims it's already been initialized

It seems like you deployed your token in deploy script, so have you passed the right contract address in upgrade script?