I’m unable to transfer ownership of a UUPSUpgradeable + OwnableUpgradeable to a Gnosis Safe per the tutorial here: OpenZeppelin Upgrades: Step by Step Tutorial for Hardhat by @abcoathup
Environment
"@openzeppelin/contracts": "^4.0.0",
"@openzeppelin/contracts-upgradeable": "^4.1.0",
"solc": "0.8.2",
"hardhat": "^2.0.8",
"@nomiclabs/hardhat-ethers": "^2.0.0",
"@nomiclabs/hardhat-etherscan": "^2.1.2",
"@nomiclabs/hardhat-waffle": "^2.0.0",
"@opengsn/gsn": "^2.1.0",
"@openzeppelin/hardhat-upgrades": "^1.6.0",
"chai": "^4.2.0",
"ethereum-waffle": "^3.0.0",
"ethers": "^5.0.0",
"hardhat": "^2.0.8",
Details
What’s the recommended way to transfer ownership of of a UUPSUpgradeable Contract to a Gnosis Safe? The goal is to use Defender + Gnosis to upgrade this. The contract in question inherits from: Initializable, ERC2771ContextUpgradeable, UUPSUpgradeable, OwnableUpgradeable
Code to reproduce
When this code is run:
import { upgrades } from "hardhat";
const GNOSIS_SAFE = '0x9E2028cd1Fb68b908cF49F4743f2E52d3c0A7e9b';
async function main () {
console.log('Transferring ownership of ProxyAdmin...');
await upgrades.admin.transferProxyAdminOwnership(GNOSIS_SAFE);
console.log('Transferred ownership of ProxyAdmin to:', GNOSIS_SAFE);
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
Fails with error:
Transferring ownership of ProxyAdmin...
Error: No ProxyAdmin was found in the network manifest
at getManifestAdmin (.../node_modules/@openzeppelin/hardhat-upgrades/src/admin.ts:57:11)
at Object.transferProxyAdminOwnership (...node_modules/@openzeppelin/hardhat-upgrades/src/admin.ts:29:19)
at main (.../scripts/transfer-ownership.ts:7:3)
This makes sense because there is no admin entry in the rinkeby.json config. If there was one, we would get the warning:
Warning: A proxy admin was previously deployed on this network
This is not natively used with the current kind of proxy ('uups').
Changes to the admin will have no effect on this new proxy.
For context, the script was deployed with:
import { ethers, upgrades } from "hardhat";
async function main() {
const RINKEBY_TRUSTED_FORWARDER = '0x956868751Cc565507B3B58E53a6f9f41B56bed74'
const MyContractFactory = await ethers.getContractFactory("MyContract");
const myContract = await upgrades.deployProxy(MyContractFactory, [RINKEBY_TRUSTED_FORWARDER], {kind: 'uups'});
console.log("Deployed to:", myContract.address);
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
So what’s the recommended way to do the upgrade, while preserving the right configuration settings here for future upgrades?