Update the administrator with the command set-admin

Hi everyone, sorry that I reply to this thread (Full start-to-finish OpenZeppelin workflow for CLI deployment and upgrades?) but I’m in a similar scenario.

I was trying to update the administrator with the command set-admin, and as the project has only one contract I ended up changing the proxy admin of that contract. The transaction was sent calling the function changeProxyAdmin with the contract proxy and the new address. But I noticed that the proxyAdmin owner is still the original address (the one that I’m trying to change)

So, I have the following questions:

  1. Was this change enough to upgrade the contract of the project in the future? I understand that it wasn’t.
    As per Oleg’s question above I think that the correct way is to: update the contract proxy back to the proxyAdmin address and change the owner of the proxyAdmin to a new Address, right?

  2. To update the owner of the proxyAdmin I just have to use the oz set-admin and in the interactive console select “All instances”, right?

With the set-admin [contract-proxy] [new-address] I was also getting the error Cannot call fallback function from the proxy admin when I used that address to call a function from the contract, that I believe it’s due the “transparent proxy pattern”, right?

1 Like

Hi @ragonzal,

Welcome to the community :wave:

If I understand correctly, you ran set-admin for a single contract.
This changed the admin of the proxy from the Proxy Admin contract to the address that you supplied.

If you want to upgrade the contract in future using the CLI, then you would need to change the admin of the proxy from your specified address back to the Proxy Admin contract (not via the CLI), you could then upgrade via the CLI.

There isn’t a CLI mechanism to transfer the ownership of the Proxy Admin contract. You would need to call transferOwnership function of the Proxy Admin contract.

Update: If you set-admin on the entire project you can transfer the ownership of the ProxyAdmin contract itself.

Hi @abcoathup, thanks for the answer.

My main goal was to be able to upgrade the contract from a new address and throw away the one I used for deploying and upgrading until now (making sure no one else can use it either).

So just to be sure the correct steps are: setting the contract admin back of my contract to the Proxy Admin (so that it can be upgraded) and the transfer ownership of the Proxy Admin to a new address, right?

Can’t I use the command set-admin passing the address of the Proxy Admin? Without passing a contract address as stated here: https://docs.openzeppelin.com/cli/2.8/contracts-architecture#ownership-transfer

On the other hand, what’s the user of changing the admin of a specific contract?

Thanks again!

1 Like

Hi @ragonzal,

Apologies, I have corrected my initial reply:

To deploy with one address and then change ownership to a different address you can use set-admin on the entire project which transfers ownership of the ProxyAdmin.

I would recommend documenting and testing this process:

  1. Deploy the contract, with the deploying address being the owner of the ProxyAdmin contract.
  2. Change ownership of the ProxyAdmin to a new address using set-admin for the entire project (not just a specific contract)
  3. Upgrade the contract using the CLI from the new address.

Someone may want a specific admin rather than using a ProxyAdmin contract. Though my preference would be to use ProxyAdmin.

Hi @abcoathup, thanks again for your help.

I was able to reproduce the status in a local testnet, check what have happened and test the commands to “fix” the current state of the contracts.

For anyone who is in the same situation as I was:

What happened
My OZ project had only one contract and as I wanted to change the owner (the address that was used to deploy and upgrade de contract) I incorrectly used zos set-admin MyContract NewAddress.
As a result, MyContract Proxy contract’s admin was updated to NewAddress but the ProxyAdmin's owner did not change.

As a result, the NewAddress was not able to call MyContract, my transactions failed with the message: Fail with error 'Cannot call fallback function from the proxy admin'. This is due the contracts architecture and it helped me reading this: https://docs.openzeppelin.com/upgrades/2.6/proxies#transparent-proxies-and-function-clashes

What I did afterwards
First I changed MyContract proxy admin back to the ProxyAdmin.
How? With the ABI from the AdminUpgradeabilityProxy contract, I called MyContract with NewAddress to the method changeAdmin passing the ProxyAdmin address as the param.

const ethers = require('ethers');
const adminProxyABI = [];
const provider = new ethers.providers.InfuraProvider('mainnet', 'projectId')
const wallet = new ethers.Wallet('pk',  provider);
const contract = new ethers.Contract(myContractAddress, adminProxyABI, wallet);
contract.functions.changeAdmin(proxyAdminAddress, {});

I got it from this thread: Full start-to-finish OpenZeppelin workflow for CLI deployment and upgrades?

Then I used oz set-admin (note that before I used zos set-admin, but oz worked for me), and with the CLI I put my NewAddress and then selected All instances to update.
Now I can see that the owner of the ProxyAdmin is the NewAddress :slight_smile:

Useful script
To check the data from the blockchain, I created a small script to check what was happening with my contracts:

import Web3 from "web3";
// ABIs
const proxyAdminABI = [];
const AdminUpgradeabilityProxyABI = [];
// Addresses
const proxyAdminAddress = "0x...";
const myContractAddress = "0x...";
// Instantiate contract
let web3 = new Web3(window.web3.currentProvider);
let proxyAdminContract = new web3.eth.Contract(proxyAdminABI, proxyAdminAddress);
let myContract = new web3.eth.Contract(AdminUpgradeabilityProxyABI, myContractAddress);

const main = () => {
  proxyAdminContract.methods
    .owner()
    .call(
      { from: "0x..." },
      (error, result) => {
        console.log(`Proxy admin owner: ${result}`);
      }
    );
  web3.eth.getStorageAt(
    myContract,
    "0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b",
    (error, result) => {
      console.log(`My contract admin: ${result}`);
    }
  );
  // Has to be called with the admin address
  myContract.methods
    .admin()
    .call({ from: proxyAdmin }, (error, result) => {
      console.log(`My contract proxy admin: ${result}`);
    });
};

main();
2 Likes

Hi @ragonzal,

I’m glad that you resolved. Thanks for sharing your solution with the community. Much appreciated :pray:

1 Like