Deploy ERC20Upgradeable without Proxy for governable upgrades

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 tried calling the initialize method, and it claims it's already been initialized



Comments

Popular posts from this blog

Spring Elasticsearch Operations

Object oriented programming concepts (OOPs)

Network Error and Timeout on Authorize.net JS