Upgradable contract is sucessfully created and verified but token doesn't showsup at etherscan

I created an upgradable contract. It was successfully deployed at remix. Contract is verified at etherscan.
Contract :

Below openzeppelin code is used:

// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.20;

import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

contract Souzacoin is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, ERC20PausableUpgradeable, OwnableUpgradeable, ERC20PermitUpgradeable, ERC20VotesUpgradeable, UUPSUpgradeable {
    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize(address initialOwner) initializer public {
        __ERC20_init("Souzacoin", "SOOZ");
        __ERC20Burnable_init();
        __ERC20Pausable_init();
        __Ownable_init(initialOwner);
        __ERC20Permit_init("Souzacoin");
        __ERC20Votes_init();
        __UUPSUpgradeable_init();

        _mint(msg.sender, 50000000000 * 10 ** decimals());
    }

    function pause() public onlyOwner {
        _pause();
    }

    function unpause() public onlyOwner {
        _unpause();
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }

    function _authorizeUpgrade(address newImplementation)
        internal
        onlyOwner
        override
    {}

    // The following functions are overrides required by Solidity.

    function _update(address from, address to, uint256 value)
        internal
        override(ERC20Upgradeable, ERC20PausableUpgradeable, ERC20VotesUpgradeable)
    {
        super._update(from, to, value);
    }

    function nonces(address owner)
        public
        view
        override(ERC20PermitUpgradeable, NoncesUpgradeable)
        returns (uint256)
    {
        return super.nonces(owner);
    }
}

Problem is :

  1. Token details is not showing up at etherscan. Why?
  2. For token creation I paid 200+ $ as gas fees, still didn’t receive any new created token at creator’s wallet address.(0x46e9c2e162bC81FC69dc17579bAB17557CbCA9D2).
  3. Cannot import the same token contract address at Metamask wallet. When I enter the contract address at Metamask custom token field, it doesn’t auto enter symbol and decimal, therefore unable to import contract address.
1 Like

That looks like an implementation contract. You need to deploy a proxy contract using that implementation address, and call your initialize function through the proxy. See https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies to understand the concepts. Remix has some documentation on proxy deployments at https://remix-ide.readthedocs.io/en/latest/run_proxy_contracts.html. I suggest you test out the deployment steps on testnets before doing so on mainnet.

Can you provide me the code to deploy proxy contract. It will be really helpful.
Implementation contract address is:

0xE1Aa42446f627e00119148fb880b76fDD8045b38

You can use Hardhat Upgrades. In your Hardhat script, you can make it import your existing implementation address and not deploy another implementation, by doing something like the following:

const { ethers, upgrades } = require("hardhat");

async function main() {
  const MyContract = await ethers.getContractFactory("Souzacoin");
  await upgrades.forceImport(YOUR_IMPLEMENTATION_ADDRESS, MyContract);
  const proxy = await upgrades.deployProxy(MyContract, [INITIAL_OWNER_ADDRESS], { redeployImplementation: 'never' });
  await proxy.waitForDeployment();
  console.log("Proxy deployed to:", await proxy.getAddress());
}

main();

But again, you should test locally and/or on testnets before doing it on mainnet.

Sir, if you look at the code, I have used OpenZeppelin's wizard and chosen UUPS upgradable contract, to do deployed process. In this case obviously two contract should have been created( implementation & proxy contract). In this case did both contract is created or not?

When I checked the etherscan through my wallet address (from which I paid the gas fees: 0x46e9c2e162bC81FC69dc17579bAB17557CbCA9D2).
I found only one transcation record of implementation contract.

My problem is:

  1. How to know whether two contract is deployed or not?
    If two of them is deployed then where is the proxy contract details? Where to find it? How to find the contract address of it?

While deploying UUPS upgradable contract, does one or two seperate transcation takes place?

I remember, while initiating deployment of contract, I did only one transcation and paid gas fees of 200+.

Does it means I only paid for implementation contract?
And proxy contract transcation didn't take place?

From your wallet address, it looks like only the implementation was deployed. You did not deploy the proxy contract yet. If you do, you should see another transaction for the proxy deployment.

While deploying UUPS upgradable contract, does one or two seperate transcation takes place?

You should see two: the implementation first, then the proxy.

I got below erc1967proxy code to dedeploy proxy contract. Which has got complied and ready to deploy, but its asking me bytes_data or _ Data

  1. What is that data, where to get it from. Please help me to find it?

  2. Although the below code has got compiled, still is it correct to deploy? Am I wrong somewhere in the code?

Below is the code which I am using:

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol)

pragma solidity ^0.8.20;

import {Proxy} from "../Proxy.sol";
import {ERC1967Utils} from "./ERC1967Utils.sol";

/**
 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
 * implementation address that can be changed. This address is stored in storage in the location specified by
 * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967], so that it doesn't conflict with the storage layout of the
 * implementation behind the proxy.
 */
contract ERC1967Proxy is Proxy {
    /**
     * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.
     *
     * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an
     * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.
     *
     * Requirements:
     *
     * - If `data` is empty, `msg.value` must be zero.
     */
    constructor(bytes memory _data) payable {
        // Replace the address below with the address of the already deployed implementation contract
        address implementation = 0xE1Aa42446f627e00119148fb880b76fDD8045b38;
        ERC1967Utils.upgradeToAndCall(implementation, _data);
    }

    /**
     * @dev Returns the current implementation address.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using
     * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
     */
    function _implementation() internal view virtual override returns (address) {
        return ERC1967Utils.getImplementation();
    }
}


For _data, see Manual Deploy: ERC1967Proxy + Remix (to understand how it's done) - #6 by ericglau

That proxy looks ok to me.

By copy pasting ABI from my implementation contract and auto parse it at https://abi.hashex.org/

I found encoded ABI out put of each constructors.

But it shows around 30+ constructors like
InvalidInitialization()
initialize(address)
ERC1967NonPayable()
EnforcedPause().....

E.g. For InvalidInitialization()
I found encoded data is f92ee8a9

My question is: From those 30+ constructors, which one to choose and find encoded data of it ?

_data should be the encoding of your initialize function along with its parameters.

I will say this one last time: test on testnets first!

1 Like