Create upgradeable ERC20

I m trying to use ERC20Upgradeable.sol to create a basic token with name symbol and initial supply … am not sure how to go about defining it in the initializer so the name and symbol can be shown and total supply to show the initial supply… just a small example would be fine for me to understand… By the way Im using remix for writing and deploying

Regards

2 Likes

Hi @Nadim,

Welcome to the community :wave:

I recommend using OpenZeppelin Upgrades Plugins for Truffle and Hardhat if you want to deploy and test upgradeable contracts: https://docs.openzeppelin.com/upgrades-plugins/1.x/

There isn’t an Upgrades Plugin for Remix, so you would need to deploy the implementation contract, followed by the proxy (and optionally a ProxyAdmin) yourself. The Upgrades Plugins perform upgrade safety checks and make it easy to write high level tests for upgradeable contracts.

I suggest looking at the following Step by Step Tutorials:

I created a very simple example ERC20 contract and deployed it to the inbuilt Truffle development network (using the setup from the Step by Step tutorial for Truffle).

MyToken.sol

This example token has a fixed supply that is minted to the deployer of the contract.

// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;

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

contract MyToken is Initializable, ERC20Upgradeable {
    function initialize(string memory name, string memory symbol, uint256 initialSupply) public virtual initializer {
        __ERC20_init(name, symbol);
        _mint(_msgSender(), initialSupply);
    }
}

2_deploy_token.js

The token is initialized with the name, symbol and the initial supply.

// migrations/2_deploy_token.js
const MyToken = artifacts.require('MyToken');
 
const { deployProxy } = require('@openzeppelin/truffle-upgrades');
 
module.exports = async function (deployer) {
  await deployProxy(MyToken, ['My Token', 'TKN', '100000000000000000000000'], { deployer, initializer: 'initialize' });
};

Truffle console

I deployed the token using migrate and then interacted with the upgradeable contract.

$ npx truffle develop
Truffle Develop started at http://127.0.0.1:9545/
...

truffle(develop)> migrate

Compiling your contracts...
===========================
> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/MyToken.sol
...

Starting migrations...
======================
> Network name:    'develop'
> Network id:      5777
> Block gas limit: 6721975 (0x6691b7)


1_initial_migration.js
======================
...

2_deploy_token.js
=================

   Deploying 'MyToken'
   -------------------
   > transaction hash:    0x508efaac2ff912035645518ee02aee25d11403728d8acf37aca2d7c2d635e7bb
   > Blocks: 0            Seconds: 0
   > contract address:    0xDEE9411430c7Dd9b67fC6DA723DE729AdAB50AD7
...

   Deploying 'ProxyAdmin'
   ----------------------
   > transaction hash:    0xd254a960020144c71ab1e28164cd6d91d53cea238f4ca109fb05f0594fe6e5ba
   > Blocks: 0            Seconds: 0
   > contract address:    0xc105BA878b6dE2472D441F0f2C4709fA622208f3
...

   Deploying 'AdminUpgradeabilityProxy'
   ------------------------------------
   > transaction hash:    0x4367f909eb988d940a1df1dc8788b76bf7b2cb60bc859b56d7519a453ecec98d
   > Blocks: 0            Seconds: 0
   > contract address:    0xB715B0DAF6097Be133A1E09AF21a84719582E720
...

truffle(develop)> token = await MyToken.deployed()
undefined
truffle(develop)> token.address
'0xB715B0DAF6097Be133A1E09AF21a84719582E720'
truffle(develop)> token.name()
'My Token'
truffle(develop)> token.symbol()
'TKN'
truffle(develop)> (await token.totalSupply()).toString()
'100000000000000000000000'
truffle(develop)> (await token.balanceOf(accounts[0])).toString()
'100000000000000000000000'
3 Likes

Thanks … that solved my purpose as was banging my head on using remix …

1 Like

Everything works as needed just followed the above procedure but when I run this (await token.balanceOf(accounts[0])).toString() … the value returned is always 0… any ideas why is it so?

1 Like

Hi @Nadim,

When we run migrate it should be deploying from accounts[0] which is then minted the total supply.

What do you get when you run (await token.balanceOf(accounts[0])).toString()?

If you close Truffle development console, you will need to migrate again when you start Truffle development console.

I was getting 0 ... even though the totalSupply gave the correct value... I figured that out I was trying to add decimals in the contract ... while I was setting value through deploy.js ...

1 Like

Hi @Nadim,

Does that mean you have resolved it? Otherwise feel free to share your contract and migration script and I can try it out.

yes have solved it … was my mistake putting 10 ** uint256(decimals()) in contract and also passing the value through truffle… i removed the one from the contract and just passed the value through truffle and it all was set

1 Like

2 posts were split to a new topic: Create upgradeable ERC20 token