Deploying ERC-20 tokens
⚠️

Public Goods Network is shutting down.
To claim funds to your L1 address, please follow the steps in Claiming Old Funds.


Deploying ERC-20 Tokens to PGN

Introduction

This guide is designed for developers and teams looking to deploy ERC-20 tokens on the PGN network. There are two recommended processes that you can use. For those that are not comfortable with coding, deploying via a user interface (UI) can significantly simplify the process.

  • UI-based deployment
  • Deploy using Hardhat

For both, you will need the following:

Table of contents

UI-based deployment

Use the following UI to deploy an ERC-20:

https://github.com/publicgoodsnetwork/pgn-monorepo/blob/erc20-deployer-ui/packages/react/src/components/DeployERC20.tsx (opens in a new tab)

##Deploy with Hardhat

The following link will take you to some code in Hardhat to deploy a standard Optimism ERC20.

Please note that this will not work with many of the stable coins since they have different constructor arguments than just name and symbol.

https://github.com/publicgoodsnetwork/pgn-monorepo/blob/main/packages/erc20-deployer/hardhat.config.ts#L33 (opens in a new tab)

Finding the correct token code to deploy

Ideally ask the owner of the token (for example, Circle for USDC) to provide a link to the contract on an OP Stack chain. (Note that Arbitrum will not work, but Base or Optimism will).

Another option is to find the token folder in the following link: https://github.com/ethereum-optimism/ethereum-optimism.github.io/blob/master/data/USDC/data.json (opens in a new tab)

Then copy the Base contract address for that token, and search for it in the Base Explorer (opens in a new tab).

Here is an example of USDC’s contract address on Base’s Explorer: https://basescan.org/address/0x833589fcd6edb6e08f4c7c32d4f71b54bda02913#readProxyContract (opens in a new tab)

You’ll find the implementationContract (address) at the bottom of the page

Navigate to that contract address to find the proper code for deployment.

Here is an example of the USDC implementationContract: https://basescan.org/address/0x6d0c9a70d85e42ba8b76dc06620d4e988ec8d0c1#code (opens in a new tab)

Considerations when deploying

To deploy certain contract, we need to consider a few things.

  • What are the arguments to deploy this/these contract(s) with?
  • Does the Proxy contract has a constructor function (with the implementation address)
  • Has this contract been upgraded and what calls do we need to make to upgrade it?

In the Base/USDC example, we find 3 initialize functions: initialize, initializeV2, initializeV2_1. These must be called in a specific order since the code checks for variables set in each of the initialize functions (initialized and _initializedVersion).

Please note: Constructor functions are called when contract is deployed, initialize is called after deployment (to complicate things, these initialize functions are named by the contract devs and might vary between tokens)

Steps to deploy an example USDC contract

Here is the implementationContract (opens in a new tab) for USDC on Base.

  1. Deploy the implementation contract (FiatTokenV2_1.sol)
  2. Call initialize (specified in FiatTokenV1.sol) with these parameters: tokenName, tokenSymbol, tokenCurrency, tokenDecimals, newMasterMinter, newPauser, newBlacklister, and newOwner
  3. Call initializeV2 (specified in FiatTokenV2.sol) with parameter newName (this is the just token name: "USD Coin")
  4. Call initializeV2_1 with a lostAndFound address ("The address to which the locked funds are sent")
  5. Deploy FiatTokenProxy.sol with the address of the deployed FiatTokenV2_1.sol as parameter implementationContract

Add the token to the PGN bridge

The final step in the process is making sure the token is available via the PGN bridge.

Please make sure you add the token, similarly to how USDT was added: https://github.com/publicgoodsnetwork/pgn-monorepo/pull/6/files (opens in a new tab)