ERC-20 implementation in Blockchain / Solidity - Time & Space Complexity
When working with ERC-20 tokens, it's important to understand how the time it takes to run functions changes as the number of users or transactions grows.
We want to know how the cost of operations like transferring tokens or checking balances grows with more users.
Analyze the time complexity of the following ERC-20 transfer function.
function transfer(address to, uint256 amount) public returns (bool) {
require(balanceOf[msg.sender] >= amount, "Insufficient balance");
balanceOf[msg.sender] -= amount;
balanceOf[to] += amount;
emit Transfer(msg.sender, to, amount);
return true;
}
This function moves tokens from the sender to another address and updates balances.
Look for loops or repeated steps inside the function.
- Primary operation: Simple balance checks and updates.
- How many times: Each call runs these steps once, no loops or recursion.
The function does the same fixed steps no matter how many users or tokens exist.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 5 steps |
| 100 | 5 steps |
| 1000 | 5 steps |
Pattern observation: The number of operations stays the same even if more users or tokens exist.
Time Complexity: O(1)
This means the transfer function takes the same amount of time no matter how many users or tokens there are.
[X] Wrong: "The transfer function takes longer as more users hold tokens."
[OK] Correct: The function only updates balances for two addresses, so it does not check or loop through all users.
Understanding that simple token transfers run in constant time helps you explain how blockchain operations stay efficient even as networks grow.
"What if the transfer function needed to update a list of all token holders? How would the time complexity change?"
Practice
balanceOf function in an ERC-20 token contract?Solution
Step 1: Understand the role of
ThebalanceOfbalanceOffunction returns how many tokens a given address owns.Step 2: Compare with other functions
Functions liketransfermove tokens,approveallows spending, and minting creates tokens. These are different from checking balance.Final Answer:
To check the token balance of a specific address -> Option CQuick Check:
balanceOf= check balance [OK]
- Confusing balanceOf with transfer function
- Thinking approve checks balances
- Mixing minting with balance checking
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 AQuick Check:
transfer(to, amount) returns bool [OK]
- Swapping parameter order
- Omitting return type
- Adding extra parameters not in standard
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?Solution
Step 1: Check balance condition
The function checks ifbalances[msg.sender]is at leastamount. Here, 50 < 60, so condition fails.Step 2: Determine function return
Since condition fails, the function skips token transfer and returnsfalse.Final Answer:
false -> Option DQuick Check:
Insufficient balance returns false [OK]
- Assuming transfer throws error on insufficient balance
- Thinking it returns true anyway
- Confusing return value with balance amount
approve function snippet:mapping(address => mapping(address => uint256)) allowances;
function approve(address spender, uint256 amount) public returns (bool) {
allowances[msg.sender][spender] = amount;
return true;
}Solution
Step 1: Review ERC-20 approve requirements
The standard requires emitting anApprovalevent after changing allowance for transparency.Step 2: Check function code
The function sets allowance but does not emit theApprovalevent, missing a key part of the standard.Final Answer:
Should emit an Approval event after setting allowance -> Option BQuick Check:
approve must emit Approval event [OK]
- Ignoring event emission
- Checking balance in approve (not required)
- Decreasing allowance instead of setting
Solution
Step 1: Understand pause feature integration
To pause transfers, the contract needs a state variable likepausedand checks in transfer functions.Step 2: Check ERC-20 compliance
Removing or renamingtransferbreaks the standard. ChangingbalanceOfoutput 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 AQuick Check:
Pause by require(!paused) in transfer functions [OK]
- Removing or renaming standard functions
- Changing balanceOf behavior
- Adding extra steps users must call
Ready to prove it?
Pass the test and this pattern moves unknown
