📖 Scenario: You are creating a simple cryptocurrency token on the Ethereum blockchain. This token will follow the ERC-20 standard, which means it has specific rules for how tokens are transferred and tracked.Imagine you want to create your own digital coins that people can send to each other, check balances, and approve others to spend on their behalf.
🎯 Goal: Build a basic ERC-20 token contract in Solidity that allows users to check balances, transfer tokens, and approve others to spend tokens for them.
📋 What You'll Learn
Create a contract named SimpleToken
Define state variables for name, symbol, decimals, and totalSupply
Create a mapping called balances to track token balances
Create a mapping called allowances to track approved spending
Implement balanceOf, transfer, approve, and transferFrom functions
Emit Transfer and Approval events appropriately
💡 Why This Matters
🌍 Real World
ERC-20 tokens are the most common standard for creating cryptocurrencies and digital assets on Ethereum and compatible blockchains. They enable easy token transfers and integration with wallets and exchanges.
💼 Career
Understanding ERC-20 token implementation is essential for blockchain developers working on decentralized finance (DeFi), NFT projects, and custom token creation.
Progress0 / 4 steps
1
Set up the contract and state variables
Create a Solidity contract named SimpleToken. Inside it, declare public state variables string name set to "SimpleToken", string symbol set to "STK", uint8 decimals set to 18, and uint256 totalSupply set to 1000000 * 10 ** 18. Also, create a mapping(address => uint256) balances to hold token balances.
Blockchain / Solidity
Hint
Start by declaring the contract and the variables exactly as described. Use public to allow reading these variables from outside.
2
Initialize balances and add allowances mapping
Add a constructor to the SimpleToken contract that assigns the entire totalSupply to the contract deployer's address using msg.sender. Also, declare a mapping(address => mapping(address => uint256)) allowances to track approved spending.
Blockchain / Solidity
Hint
Use a constructor function to set the initial balance. Declare the nested mapping for allowances exactly as shown.
3
Implement transfer, approve, and transferFrom functions
Inside SimpleToken, implement three functions: transfer, approve, and transferFrom. transfer should move tokens from msg.sender to a recipient if the sender has enough balance. approve should allow a spender to spend a specified amount from the caller's balance. transferFrom should allow a spender to transfer tokens from an owner's balance if approved. Use require to check balances and allowances. Update balances and allowances accordingly.
Blockchain / Solidity
Hint
Use require to check conditions. Update balances and allowances carefully. Don't forget to emit events after changes.
4
Add balanceOf function and test output
Add a public view function balanceOf that takes an address account and returns the token balance of that account from balances. Then, write a simple test line to print the balance of the contract deployer (msg.sender) using balanceOf(msg.sender). Since Solidity contracts do not print, simulate this by returning the balance in a public function called testBalance.
Blockchain / Solidity
Hint
The balanceOf function returns the balance for any address. The testBalance function returns the deployer's balance to simulate output.
Practice
(1/5)
1. What is the main purpose of the balanceOf function in an ERC-20 token contract?
easy
A. To approve another address to spend tokens
B. To transfer tokens from one address to another
C. To check the token balance of a specific address
D. To mint new tokens to an address
Solution
Step 1: Understand the role of balanceOf
The balanceOf function returns how many tokens a given address owns.
Step 2: Compare with other functions
Functions like transfer move tokens, approve allows spending, and minting creates tokens. These are different from checking balance.
Final Answer:
To check the token balance of a specific address -> Option C
Quick Check:
balanceOf = check balance [OK]
Hint: balanceOf always returns token count for an address [OK]
Common Mistakes:
Confusing balanceOf with transfer function
Thinking approve checks balances
Mixing minting with balance checking
2. Which of the following is the correct Solidity function signature for transferring tokens in an ERC-20 contract?
easy
A. function transfer(address to, uint256 amount) public returns (bool);
B. function transfer(uint256 amount, address to) public returns (bool);
C. function transfer(address to) public returns (uint256);
D. function transfer(address from, address to, uint256 amount) public;
Solution
Step 1: Recall ERC-20 transfer signature
The standard transfer function takes the recipient address first, then the amount, and returns a boolean.
Step 2: Check each option
function transfer(address to, uint256 amount) public returns (bool); matches the standard: transfer(address to, uint256 amount) public returns (bool). Others have wrong parameter order, missing return, or extra parameters.
Final Answer:
function transfer(address to, uint256 amount) public returns (bool); -> Option A
Quick Check:
transfer(to, amount) returns bool [OK]
Hint: transfer always has (address to, uint256 amount) and returns bool [OK]
Common Mistakes:
Swapping parameter order
Omitting return type
Adding extra parameters not in standard
3. Given this snippet from an ERC-20 contract:
mapping(address => uint256) balances;
function transfer(address to, uint256 amount) public returns (bool) {
if (balances[msg.sender] >= amount) {
balances[msg.sender] -= amount;
balances[to] += amount;
return true;
}
return false;
}
What will transfer return if msg.sender has 50 tokens and tries to send 60 tokens?
medium
A. true
B. Returns the remaining balance
C. Throws an error
D. false
Solution
Step 1: Check balance condition
The function checks if balances[msg.sender] is at least amount. Here, 50 < 60, so condition fails.
Step 2: Determine function return
Since condition fails, the function skips token transfer and returns false.
Final Answer:
false -> Option D
Quick Check:
Insufficient balance returns false [OK]
Hint: Transfer returns false if sender lacks enough tokens [OK]
Common Mistakes:
Assuming transfer throws error on insufficient balance
Thinking it returns true anyway
Confusing return value with balance amount
4. Identify the bug in this ERC-20 approve function snippet:
B. Should emit an Approval event after setting allowance
C. Should check if amount is less than balance
D. Should decrease allowance instead of setting it
Solution
Step 1: Review ERC-20 approve requirements
The standard requires emitting an Approval event after changing allowance for transparency.
Step 2: Check function code
The function sets allowance but does not emit the Approval event, missing a key part of the standard.
Final Answer:
Should emit an Approval event after setting allowance -> Option B
Quick Check:
approve must emit Approval event [OK]
Hint: approve must emit Approval event to follow standard [OK]
Common Mistakes:
Ignoring event emission
Checking balance in approve (not required)
Decreasing allowance instead of setting
5. You want to add a feature to your ERC-20 token that prevents transfers when the contract is paused. Which is the best way to implement this without breaking the ERC-20 standard?
hard
A. Add a paused boolean and require it false in transfer and transferFrom functions
B. Remove the transfer function and replace it with a new function that checks pause
C. Add a new function pauseTransfer that users must call before transferring
D. Modify the balanceOf function to return zero when paused
Solution
Step 1: Understand pause feature integration
To pause transfers, the contract needs a state variable like paused and checks in transfer functions.
Step 2: Check ERC-20 compliance
Removing or renaming transfer breaks the standard. Changing balanceOf output breaks expected behavior. Adding a separate function for pause is not standard.
Final Answer:
Add a paused boolean and require it false in transfer and transferFrom functions -> Option A
Quick Check:
Pause by require(!paused) in transfer functions [OK]
Hint: Use a paused flag and require it false in transfer methods [OK]
Common Mistakes:
Removing or renaming standard functions
Changing balanceOf behavior
Adding extra steps users must call
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.