This project contains two ERC20 token implementations:
- Token.sol — A custom, lightweight, gas-optimized ERC20 written in Solidity + Yul.
- Token2.sol — A standard implementation extending OpenZeppelin ERC20.
The purpose of this repository is to compare performance and gas efficiency between a hand-optimized ERC20 implementation and the official OZ version.
This project demonstrates how a manually optimized ERC20 implementation can outperform OpenZeppelin’s ERC20 in:
- Deployment cost
- Mint/burn costs
- Approvals and allowances
- General state-changing operations
…while maintaining full ERC20 compliance.
This repository includes:
- ✔ Source contracts
- ✔ Foundry test suite
- ✔ Mainnet-fork & Sepolia gas reports
- ✔ Deep efficiency comparison
Gas reports were generated on:
- Local Foundry test environment
- Ethereum Mainnet fork
- Sepolia testnet fork
Results remained consistent across networks.
| Metric | Value |
|---|---|
| Deployment Gas | 711,427 |
| Deployment Size | 3728 bytes |
| Function | Min | Avg | Median | Max | Calls |
|---|---|---|---|---|---|
| allowance | 3312 | 3312 | 3312 | 3312 | 4 |
| approve | 22052 | 40613 | 46801 | 46801 | 4 |
| balanceOf | 2720 | 2720 | 2720 | 2720 | 11 |
| burn | 22145 | 24078 | 24078 | 26012 | 2 |
| decimals | 427 | 427 | 427 | 427 | 1 |
| mint | 22079 | 61695 | 66648 | 66648 | 9 |
| name | 3330 | 3330 | 3330 | 3330 | 1 |
| symbol | 3373 | 3373 | 3373 | 3373 | 1 |
| totalSupply | 2317 | 2317 | 2317 | 2317 | 3 |
| transfer | 22190 | 33649 | 26852 | 51906 | 3 |
| transferFrom | 25284 | 39104 | 39104 | 52924 | 2 |
| Metric | Value |
|---|---|
| Deployment Gas | 955,366 |
| Deployment Size | 4870 bytes |
| Function | Min | Avg | Median | Max | Calls |
|---|---|---|---|---|---|
| allowance | 3245 | 3245 | 3245 | 3245 | 4 |
| approve | 22356 | 40794 | 46940 | 46940 | 4 |
| balanceOf | 2850 | 2850 | 2850 | 2850 | 11 |
| burn | 22374 | 25081 | 25081 | 27788 | 2 |
| decimals | 427 | 427 | 427 | 427 | 1 |
| mint | 22308 | 63754 | 68935 | 68935 | 9 |
| name | 3330 | 3330 | 3330 | 3330 | 1 |
| symbol | 3373 | 3373 | 3373 | 3373 | 1 |
| totalSupply | 2477 | 2477 | 2477 | 2477 | 3 |
| transfer | 22478 | 33297 | 25204 | 52211 | 3 |
| transferFrom | 25799 | 39712 | 39712 | 53626 | 2 |
Same results as mainnet fork (expected).
| Function | Min | Avg | Median | Max | Calls |
|---|---|---|---|---|---|
| allowance | 3312 | 3312 | 3312 | 3312 | 4 |
| approve | 22052 | 40613 | 46801 | 46801 | 4 |
| balanceOf | 2720 | 2720 | 2720 | 2720 | 11 |
| burn | 22145 | 24078 | 24078 | 26012 | 2 |
| decimals | 427 | 427 | 427 | 427 | 1 |
| mint | 22079 | 61695 | 66648 | 66648 | 9 |
| name | 3330 | 3330 | 3330 | 3330 | 1 |
| symbol | 3373 | 3373 | 3373 | 3373 | 1 |
| totalSupply | 2317 | 2317 | 2317 | 2317 | 3 |
| transfer | 22190 | 33649 | 26852 | 51906 | 3 |
| transferFrom | 25284 | 39104 | 39104 | 52924 | 2 |
| Function | Min | Avg | Median | Max | Calls |
|---|---|---|---|---|---|
| allowance | 3245 | 3245 | 3245 | 3245 | 4 |
| approve | 22356 | 40794 | 46940 | 46940 | 4 |
| balanceOf | 2850 | 2850 | 2850 | 2850 | 11 |
| burn | 22374 | 25081 | 25081 | 27788 | 2 |
| decimals | 427 | 427 | 427 | 427 | 1 |
| mint | 22308 | 63754 | 68935 | 68935 | 9 |
| name | 3330 | 3330 | 3330 | 3330 | 1 |
| symbol | 3373 | 3373 | 3373 | 3373 | 1 |
| totalSupply | 2477 | 2477 | 2477 | 2477 | 3 |
| transfer | 22478 | 33297 | 25204 | 52211 | 3 |
| transferFrom | 25799 | 39712 | 39712 | 53626 | 2 |
forge installforge testforge test --gas-reportforge test --fork-url $MAINNET_RPC --gas-reportforge test --fork-url $SEPOLIA_RPC --gas-reportcontracts/
├── ERC20.sol
├── IERC20.sol
├── helpers/
│ ├── IERC20Errors.sol
│ └── ERC20Internals.sol
test/
├── Token.sol
├── Token2.sol
├── Token.t.sol
└── Token2.t.sol
README.md
foundry.tomlMIT License — free for use and modification.
Pull requests and improvements are welcome.