Search code examples
typescriptsolidityhardhatopenzeppelin

How to deploy an upgradable erc20


I have a simple ERC20Upgradable:

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

contract GovernanceToken is Initializable, ERC20Upgradeable, OwnableUpgradeable, UUPSUpgradeable {
    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize() initializer public {
        __ERC20_init("Governance Token", "GT");
        __Ownable_init();
        __UUPSUpgradeable_init();

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

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

    function _authorizeUpgrade(address newImplementation)
        internal
        onlyOwner
        override
    {}
}

I'm trying to figure out how to deploy this properly. I was using my old deployment script but it seems to fail.

const { getNamedAccounts, deployments, network } = hre
const { deploy, log } = deployments
const { deployer } = await getNamedAccounts()

const governanceTokenResult = await deploy(GOVERNANCE_TOKEN_NAME, {
  from: deployer,
  args: [],
  log: true,
  // we need to wait if on a live network so we can verify properly
  waitConfirmations: networkConfig[network.name].blockConfirmations || 1,
})

if (!developmentChains.includes(network.name) && process.env.ETHERSCAN_API_KEY) {
  await verify(governanceTokenResult.address, [], "contracts/GovernanceToken.sol:GovernanceToken")
}

const governanceToken = await ethers.getContractAt(GOVERNANCE_TOKEN_NAME, governanceTokenResult.address);

const name = await governanceToken.name();
log(`name: ${name}`);

I tried the contract compiles and deploys however, I just calling name after to verify it worked properly, but nothing is returned. I tried to manually call initialize but it seems to automatically get called when deploying the token.

how can I deploy an upgradable token?


Solution

  • I can see that you're using hardhat-deploy for deployments and testing, I suggest you go through the Deploying and Upgrading Proxies section of the documentation, your deployment script seems to be missing the proxy contract.

    The documentation hasn't been updated with UUPS as an option but the package does support it, your deploy function should look something like this:

    await deploy(GOVERNANCE_TOKEN_NAME, {
      from: deployer,
      proxy: {
        proxyContract: 'UUPS',
      }
    });