Error: Proxy admin is not the one registered in the network manifest

:computer: Environment
Truffle v5.3.4 (core: 5.3.4)
Solidity - 0.6 (solc-js)
Node v12.18.3
Web3.js v1.3.5

:memo:Details
I am trying to do an upgradeable contract. deployment worked. First upgrade worked…then on second upgrade I get the following error:

“Error: Proxy admin is not the one registered in the network manifest”

Hi, I would like to close this topic cause it seems like this is a duplicated topic. Before posting, I think you should extensively search the internet and the forum for relevant posts. And please read this How do I ask a good question? to follow, thanks!

And there is a tutorial, I think it is helpful.

I would like to help with this but we need you to provide a lot more detail about the situation.

Are you running against Ganache or a testnet? If Ganache, is it a fork? What are the exact steps that you followed for the deployment and first upgrade, and then the second upgrade?

Thanks. It is on ropsten, contract 0x4c0D79f3fdE4455Decc9FDca56ec139BdFe42b65.

For the initial deployment I used the following deployment contract:

const { deployProxy, upgradeProxy, admin } = require('@openzeppelin/truffle-upgrades');
const Token = artifacts.require("Token");

module.exports = async function(deployer) {
  const instance = await deployProxy(Token, [], { deployer, initializer: 'init' });
  console.log('Instance', instance.address);
};

For the subsequent upgrades I created a new contract file and the following deployment code (note the “2” is just an example here, and was different for each subsequent attempt):

const { deployProxy, upgradeProxy, admin } = require('@openzeppelin/truffle-upgrades');
const Token = artifacts.require("Token_2");

module.exports = async function(deployer) {
  const instance = await upgradeProxy("0x4c0D79f3fdE4455Decc9FDca56ec139BdFe42b65", Token , { deployer });
  console.log('Instance', instance.address);
};

The first time it worked, the second time it didn’t.

Please use triple backticks to surround your code in order to get proper formatting. I’ve edited your post.

```
code here
```

Will take a look at this issue a little bit later.

1 Like

What does your network configuration look like on Truffle? (Do not share any secret information like private keys.)

This?

ropsten: {
      provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/...`),
      from: '...',
      network_id: 3,       
      gas: 7000000,      
      confirmations: 2,   
      timeoutBlocks: 200,  
      skipDryRun: true    
    },

So I tried reproducing this and was able to deploy and upgrade twice a contract on Ropsten.

I suspect that the address in your migration is wrong. I would recommend to get the address programmatically instead of hardcoding it.

One way that you can do this is by reading it from the address field of the previous version, since it will be stored in the artifact. But this may be finicky and won’t work in the future unless you commit your artifact to git.

const { deployProxy, upgradeProxy, admin } = require('@openzeppelin/truffle-upgrades');
const TokenCurrent = artifacts.require("Token");
const Token = artifacts.require("Token_2");

module.exports = async function(deployer) {
  const instance = await upgradeProxy(TokenCurrent.address, Token , { deployer });
  console.log('Instance', instance.address);
};

You can also save the address in a JSON file in one migration and read it back in the next.

When I try the way you suggest I get the error:

“Token has not been deployed to detected network” (I am using Token for the old one, and NewToken for the new one)

Also, just so I understand…is the existing address supposed to be the address for the “TransparentUpgradeableProxy”. Should this be changing?

–update. ok, so I realized that you are getting the address directly from TokenCurrent. I was trying:

const existing = await Token.deployed();

Yes although that should also work.

Yes, this is the address of the proxy, and it should not change once it’s been deployed.

If you run deployProxy in a migration (passing in the deployer argument), the plugin will store the proxy address in the artifact as a deployment of the contract. So this is why Token.address or Token.deployed() should be working.

Hello

I deleted the JSON file under the .openzeppelin file by mistake, which caused below error when I upgraded
Error: Proxy admin is not the one registered in the network manifest

What should I do? Please help me @redbeard

Can I restore it @frangio

I have fix this error.I restore the json through mock all versions upgrade process in local ganache,and get the each upgrade records,and then replace local chain net to public net contract address and txhash.Finally,it works!

1 Like

Hello @frangio ,

I'm getting the same error while trying to upgrade a contract on Mainnet, after it was originally deployed, I made the contract's DEFAULT_ADMIN_ROLE a multisig contract and renounced the role from the deployer's address; could that be why I'm getting the error? The deployer is still the current owner of the admin contract however, so it shouldn't make a difference.

Here is the mainnet.json:

{
  "manifestVersion": "3.2",
  "admin": {
    "address": "0xd4486BC17faA70D6Dbb503CE52E2A73D09A57Dc1",
    "txHash": "0x49a4f9d2c393056b7be67ef09f4e6eb9fe948a2a09a0a33fa6dd1637bcaf66fd"
  },
  "proxies": [
    {
      "address": "0x2715356BF3167Ea5cd0ea48f48eea3c1179F7A89",
      "txHash": "0x1f1411aed1689befae1be9e5fe72dbe658a907984c9ab47d1ef1cd0c8ecaf9ff",
      "kind": "transparent"
    },
    {
      "address": "0xbA88E875447Dbe1dAB4EC13135f159Aa6FAA38b3",
      "txHash": "0x6d778fc5590181d0e1224f929bd298cf50042b3eaf4f70938a475e6d9c7a40a6",
      "kind": "transparent"
    }
  ],...

I have doublechecked and the addresses in the file above are correct.

I can't figure out a solution...

Having tried to restore manually the mainnet.json file without success, I discovered the new OpenZeppelin forceImport plugin and it worked like a charm:

const { upgradeProxy, forceImport } = require("@openzeppelin/truffle-upgrades");
const MyContractV2 = artifacts.require("MyContractV2");

module.exports = async (accounts) => {
  const marketplaceProxy = await forceImport("0x...", MyContractV2, {
    from: accounts[0],
  });

  await upgradeProxy(
    marketplaceProxy.address, // mainnet proxy address
    MyContractV2,
    { from: accounts[0] }
  );
};

@Cosimo_de_Medici_di Be careful with how you use forceImport. The contract that you pass in should be the implementation that is currently being used (e.g. the v1 contract). Then you can upgrade it to the v2 contract (and the plugin would validate that the upgrade from v1 to v2 is safe).

The way that your example is set up, that looks like an upgrade from v2 to v2 (from the plugin's point of view) so would miss some validations.

So your usage should look like this:

const { upgradeProxy, forceImport } = require("@openzeppelin/truffle-upgrades");
const MyContractV1 = artifacts.require("MyContractV1");
const MyContractV2 = artifacts.require("MyContractV2");

module.exports = async (accounts) => {
  const marketplaceProxy = await forceImport("0x...", MyContractV1);

  await upgradeProxy(
    marketplaceProxy.address, // mainnet proxy address
    MyContractV2,
  );
};
1 Like

Hi @ericglau thank you very much! I just realized that in fact my deployment script ended up calling upgrade() on the proxy admin and passing the implementation address of v1 again.

Just a follow up question if I may, am I supposed to keep both v1 and v2 contracts in my project folder? I wanted the upgraded implementation to keep the same contract name as v1, since I've only done a minor change; is there a way to pass the harcoded ABI of v1 to forceImport, in order to keep only the upgraded contract file in my project folder?

Thank you in advance

@Cosimo_de_Medici_di After a contract is imported, there isn't necessarily a need to keep the source code in the project folder. So you could do this for example (assuming the actual proxy is currently using v1):

  1. Revert the contract in the project folder to v1
  2. forceImport with v1
  3. Change the source code in the project folder to v2
  4. upgradeProxy from v1 to v2

That said, it's useful to have the different versions of your contracts available so you can run local tests for upgrades.

1 Like