2022-12-28

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



No comments:

Post a Comment