Back to Lessons
Lesson 07

Minting & Burning: Token Supply Control

+15EFFORT
6 sections
mintBurn()
01
text

Minting creates new tokens out of thin air and assigns them to an address, increasing totalSupply. Burning destroys tokens from an address, decreasing totalSupply. These are not part of the core ERC-20 standard (EIP-20 does not define mint or burn functions), but they are extremely common in practice. The Proof of Effort token you are earning right now uses minting — when you complete a task, new EFFORT tokens are minted to your address.

02
code
solidity
1// Minting: create new tokens
2function _mint(address to, uint256 amount) internal {
3 require(to != address(0), "Mint to zero address");
4
5 _totalSupply += amount; // Increase total supply
6 _balances[to] += amount; // Credit the recipient
7
8 emit Transfer(address(0), to, amount); // from = 0x0 signals a mint
9}
10
11// Burning: destroy existing tokens
12function _burn(address from, uint256 amount) internal {
13 require(from != address(0), "Burn from zero address");
14
15 uint256 accountBalance = _balances[from];
16 require(accountBalance >= amount, "Burn exceeds balance");
17
18 _balances[from] = accountBalance - amount;
19 _totalSupply -= amount;
20
21 emit Transfer(from, address(0), amount); // to = 0x0 signals a burn
22}
03
text

Notice that both _mint and _burn emit a Transfer event with the zero address. This is the ERC-20 convention: Transfer(address(0), to, amount) means newly minted tokens, and Transfer(from, address(0), amount) means burned tokens. Block explorers and indexers use this pattern to track circulating supply changes.

04
note
Key Insight

Security critical: _mint and _burn are 'internal' functions — they cannot be called directly from outside the contract. The contract must expose public functions with proper access control. Common patterns include onlyOwner (centralized), role-based access (OpenZeppelin AccessControl), or algorithmic minting (like this dApp's task completion system).

05
code
solidity
1// Different minting access control patterns:
2
3// Pattern 1: Only owner can mint (centralized)
4function mint(address to, uint256 amount) external onlyOwner {
5 _mint(to, amount);
6}
7
8// Pattern 2: Role-based (multiple authorized minters)
9function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) {
10 _mint(to, amount);
11}
12
13// Pattern 3: Proof-based (this dApp's pattern!)
14function completeTask(uint256 taskId, bytes32 nonce, bytes signature) external {
15 require(verifySignature(msg.sender, taskId, nonce, signature));
16 require(!isTaskCompletedBy[msg.sender][taskId], "Already completed");
17 isTaskCompletedBy[msg.sender][taskId] = true;
18 effortToken.mint(msg.sender, tasks[taskId].rewardAmount);
19}
20
21// Pattern 4: Burn is often permissionless
22function burn(uint256 amount) external {
23 _burn(msg.sender, amount);
24}
06
text

Fixed-supply tokens (like most meme tokens) mint all tokens in the constructor and never mint again. Inflationary tokens mint on a schedule or in response to actions. Deflationary tokens incorporate burning (some tax a percentage of every transfer and burn it). Understanding mint and burn mechanics is essential for evaluating any token's economic model — if anyone can mint unlimited tokens, the token has no value.

Complete

Connect your wallet to mark this lesson as complete

Earn 15 EFFORT tokens