ERC Standards
Module 4 of Ethereum & Smart Contracts
What Are ERCs?
ERC = Ethereum Request for Comments
ERCs are standards that define common interfaces, enabling:
- Interoperability between contracts
- Composability (DeFi legos)
- Wallet support
- Exchange listings
If everyone follows the same interface, everything works together.
ERC-20: Fungible Tokens
The most important standard. Enables tokens like USDC, UNI, LINK.
The Interface
interface IERC20 {
// Total supply of tokens
function totalSupply() external view returns (uint256);
// Balance of an address
function balanceOf(address account) external view returns (uint256);
// Transfer tokens
function transfer(address to, uint256 amount) external returns (bool);
// Allowance: how much spender can spend from owner
function allowance(address owner, address spender) external view returns (uint256);
// Approve spender to spend tokens
function approve(address spender, uint256 amount) external returns (bool);
// Spend approved tokens
function transferFrom(address from, address to, uint256 amount) external returns (bool);
// Events
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
The Approve/TransferFrom Pattern
Why two-step transfers?
Direct transfer: User → Recipient
- User calls transfer()
DeFi interaction: User → Protocol → Action
1. User approves protocol (approve)
2. Protocol pulls tokens (transferFrom)
3. Protocol does something
This lets protocols operate on your behalf.
Common Extensions
| Extension | Purpose |
|---|---|
| ERC-20Permit | Gasless approvals via signatures |
| ERC-20Burnable | Tokens can be destroyed |
| ERC-20Pausable | Emergency pause functionality |
| ERC-20Snapshot | Historical balance queries |
ERC-721: Non-Fungible Tokens (NFTs)
Each token is unique. Used for digital art, collectibles, gaming.
Key Difference from ERC-20
ERC-20: "You have 100 tokens"
ERC-721: "You own token #42, token #108, and token #3256"
The Interface
interface IERC721 {
// Number of tokens owned
function balanceOf(address owner) external view returns (uint256);
// Owner of a specific token
function ownerOf(uint256 tokenId) external view returns (address);
// Transfer (requires approval)
function transferFrom(address from, address to, uint256 tokenId) external;
// Safe transfer (checks receiver can handle NFTs)
function safeTransferFrom(address from, address to, uint256 tokenId) external;
// Approve one token
function approve(address to, uint256 tokenId) external;
// Approve all tokens
function setApprovalForAll(address operator, bool approved) external;
// Events
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
}
Metadata Extension
interface IERC721Metadata {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
The tokenURI returns a link to JSON metadata:
{
"name": "CryptoPunk #7804",
"description": "An alien punk",
"image": "ipfs://...",
"attributes": [
{ "trait_type": "Type", "value": "Alien" }
]
}
ERC-1155: Multi-Token Standard
Combines fungible and non-fungible in one contract.
Use Cases
- Gaming: Swords (NFT) + Gold (fungible) in one contract
- Batch transfers: Move multiple token types atomically
- Gas efficiency: Shared contract logic
The Interface
interface IERC1155 {
// Balance of specific token ID for an owner
function balanceOf(address account, uint256 id) external view returns (uint256);
// Batch balance check
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
// Transfer single token type
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
// Transfer multiple token types
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
Comparison
| Feature | ERC-20 | ERC-721 | ERC-1155 |
|---|---|---|---|
| Token types | 1 | Many (each unique) | Many (fungible or not) |
| Batch transfers | No | No | Yes |
| Multiple tokens/contract | No | Yes | Yes |
| Gas efficiency | Good | Poor | Best |
ERC-4626: Tokenized Vaults
Standard for yield-bearing tokens (staking, lending, etc.)
The Problem Before
Every yield product had different interfaces:
- aTokens (Aave)
- cTokens (Compound)
- yTokens (Yearn)
Wallets and aggregators had to integrate each separately.
The Solution
Standard vault interface:
interface IERC4626 is IERC20 {
// Underlying asset (e.g., USDC)
function asset() external view returns (address);
// Total assets under management
function totalAssets() external view returns (uint256);
// Deposit assets, receive shares
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
// Withdraw assets by burning shares
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
// How many shares for X assets?
function convertToShares(uint256 assets) external view returns (uint256);
// How many assets for X shares?
function convertToAssets(uint256 shares) external view returns (uint256);
}
Benefits
- Universal vault interface
- Easy DeFi aggregation
- Standardized accounting
Other Important ERCs
ERC-2612: Permit (Gasless Approvals)
Approve via signature instead of transaction:
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v, bytes32 r, bytes32 s
) external;
User signs message, protocol submits it → saves gas for user.
ERC-4337: Account Abstraction
Smart contract wallets with:
- Social recovery
- Gas sponsorship
- Batch transactions
- Any signature scheme
ERC-6551: Token Bound Accounts
NFTs that own assets:
NFT #42 owns:
- 100 USDC
- NFT #101
- 0.5 ETH
Transfer NFT #42 → Transfer everything it owns
ERC-7201: Namespaced Storage
Safe storage layout for upgradeable contracts.
Creating an ERC-20 Token
Using OpenZeppelin:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor() ERC20("My Token", "MTK") {
_mint(msg.sender, 1000000 * 10**18); // 1M tokens
}
}
That's it! Full ERC-20 implementation in 10 lines.
Why Standards Matter
Interoperability
Any ERC-20 token works with:
- Every DEX (Uniswap, Curve, etc.)
- Every wallet (MetaMask, Rainbow, etc.)
- Every lending protocol (Aave, Compound, etc.)
- Every bridge
- Every aggregator
Composability
DeFi "money legos":
1. Deposit USDC into Aave → get aUSDC (ERC-20)
2. Deposit aUSDC into Yearn → get yvUSDC (ERC-4626)
3. Use yvUSDC as collateral on Maker → get DAI (ERC-20)
All possible because of standards.
Key Takeaways
- ERC-20 is foundational — fungible tokens
- ERC-721 powers NFTs — unique tokens
- ERC-1155 is versatile — multiple token types
- ERC-4626 standardizes yield — vaults
- Standards enable composability — the DeFi magic
- Use OpenZeppelin — don't reinvent the wheel
Questions to Consider
- Why does ERC-20 need approve + transferFrom?
- When would you use ERC-1155 vs ERC-721?
- How does ERC-4626 simplify DeFi integrations?
- What new standards are emerging?