Skip to content

HWyn2020/erc20-emission-token

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EmissionToken — ERC20 with Capped Supply and Pull-Based Yield Emissions

A gas-efficient ERC20 token built on OpenZeppelin with three core features: a hard supply cap, owner-controlled minting, and a pull-based emission mechanism that rewards holders proportionally over time.

Designed for Arbitrum. Tested with Hardhat. Clean code, no bloat.

Architecture

Why Pull Over Push

There are two ways to distribute emission rewards to token holders:

Push model: The owner calls a function that iterates over every holder and mints their share. Simple to understand, but the gas cost scales linearly with the number of holders. At 1,000 holders you are burning serious gas. At 10,000 you are hitting block limits.

Pull model (this contract): Each holder calls claim() to collect their own rewards. Gas cost is constant regardless of how many holders exist. The tradeoff is that holders must actively claim, but in practice this is standard behavior in DeFi and users expect it.

This contract uses the pull model. Rewards accrue per block based on the holder's current balance. A checkpoint system tracks each address's last claim block to calculate what they are owed.

Supply Cap Enforcement

The MAX_SUPPLY is immutable. Set once at deployment, cannot be changed. The mint() function and the claim() function both check against this cap before minting. Even if a holder has accrued massive pending rewards, the contract will only mint up to the remaining supply and no further.

Emission Math

rewards = (holderBalance * emissionPerBlock * blocksSinceLastClaim) / 1e18

The division by 1e18 normalizes the rate so that emissionPerBlock represents tokens emitted per block per whole token held. If you hold 1,000 tokens and the rate is 0.01, you earn 10 tokens per block.

Contract

contracts/EmissionToken.sol

Key functions:

  • mint(address to, uint256 amount) — Owner only. Respects supply cap.
  • claim() — Any holder. Mints accrued rewards to caller.
  • pendingRewards(address holder) — View. Returns unclaimed rewards.
  • setEmissionRate(uint256 newRate) — Owner only. Updates emission rate.
  • toggleEmissions() — Owner only. Turns emissions on or off.

Tests

test/EmissionToken.test.js

Coverage:

  • Deployment state validation
  • Owner minting and cap enforcement
  • Non-owner mint rejection
  • Zero address and zero amount reverts
  • Cumulative minting up to and beyond cap
  • Emission toggling
  • Reward accrual over blocks
  • Claim checkpoint reset
  • Supply cap respected during emission claims
  • Emission rate updates with event verification
  • Transfer checkpoint initialization for new holders
  • Access control on all owner functions

Run tests:

npm install
npm test

Deployment

# Copy env template and add your keys
cp .env.example .env

# Deploy to Arbitrum Sepolia (testnet)
npm run deploy:sepolia

# Deploy to Arbitrum One (mainnet)
npm run deploy:mainnet

Stack

  • Solidity 0.8.20
  • OpenZeppelin Contracts 5.0.1
  • Hardhat 2.22.0
  • Arbitrum One / Arbitrum Sepolia

License

MIT

About

ERC20 token with capped supply, owner-only minting, and pull-based emission rewards. Built for Arbitrum. Hardhat, OpenZeppelin.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors