Skip to content

earn-park/ep-park-token

Repository files navigation

ParkToken (Upgradeable ERC20 for Arbitrum One)

Upgradeable ERC20 token (capped, burnable, permit, access-controlled) deployed via Transparent Proxy on Arbitrum One.

Features

  • Capped supply with mutable cap reduction on burn
  • Burn (with or without cap reduction)
  • EIP-2612 Permit (gasless approvals)
  • Role-based access control (MINTER_ROLE, PLUGIN_ADMIN_ROLE)
  • Upgradeable via OpenZeppelin Transparent Proxy
  • Delegated plugin handler (delegatecall, can be paused)

Tech Stack

  • Hardhat + TypeScript
  • OpenZeppelin Contracts & Upgrades
  • Arbitrum One network

Directory

  • contracts/ Solidity sources
  • scripts/ Deployment & upgrade helpers
  • .openzeppelin/ Upgrade manifest (must stay committed)
  • artifacts/ + cache/ (ignored)

Environment Setup

Copy .env.example -> .env and fill values:

ARBITRUM_ONE_RPC_URL=https://arb1.arbitrum.io/rpc
PRIVATE_KEY=your_private_key_no_0x
SAFE_ADDRESS=0xYourSafeAddress
SAFE_OWNER=0xYourSafeOwnerAddress
TOKEN_CAP=100000000
CONTRACT_NAME=ParkToken
NETWORK_NAME=Arbitrum One
ARBISCAN_API_KEY=yourArbiscanKey
# Filled after deploy:
PROXY_ADDRESS=
PROXY_ADMIN_ADDRESS=
IMPLEMENTATION_ADDRESS=

Never commit .env.

Install

npm install

Compile

npm run compile

Deployment Flow

Two approaches:

  1. Simple proxy deploy (no initialize auto-call):
npm run deploy:proxy

Then prepare initialization calldata (if not using deployFlow):

npm run calldata:init

Submit initialize(cap, safe) via proxy (e.g. Gnosis Safe) once.

  1. Full flow helper (includes showing initialize calldata):
npm run deploy:flow

Records proxy, implementation, admin addresses. Update .env with PROXY_ADDRESS, PROXY_ADMIN_ADDRESS.

Initialization

Token is not initialized automatically (initializer: false). Use generated calldata with Safe as owner to set:

  • initialCap (expressed in 18 decimals in script)
  • ownerAddress (Safe)

Minting & Roles

After init, grant roles from Safe:

  • grantMinter(address)
  • grantPluginAdmin(address)

Upgrade Process

  1. Prepare upgrade & calldata for Safe:
npm run prepare:upgrade

Fill <REPLACE_WITH_ADMIN_ADDRESS> with actual ProxyAdmin and propose Safe TX using generated calldata.

  1. Alternative quick flow (direct upgrade via deployer EOA - not for production Safe):
npm run upgrade:flow

Verification

After setting env vars:

npm run verify:all

Make sure IMPLEMENTATION_ADDRESS, PROXY_ADDRESS, PROXY_ADMIN_ADDRESS are in .env.

Helper Scripts

  • npm run get:proxyAdmin reads ProxyAdmin from storage slot
  • npm run calldata:init prints initialization calldata

Security Notes

  • Do NOT remove .openzeppelin/ manifests; required for safe upgrades.
  • Proxy is deployed with unsafeAllow: ["delegatecall"] due to plugin handler usage — audit any handler.
  • Initialization must occur exactly once.
  • Keep private keys & Safe addresses secure; use a hardware wallet for deployer if possible.

Gas Reporting (optional)

Enable with:

REPORT_GAS=true npx hardhat test

(Add tests first.)

Future Improvements

  • Add unit tests for role flows
  • Add plugin handler contract example
  • Add CI (lint + compile + verify dry-run)

(Generated README for repository bootstrap.)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors