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"