ERC-20 fungible token standard in Blockchain / Solidity - Time & Space Complexity
When working with ERC-20 tokens, it's important to understand how the time to execute token operations changes as the number of users or transactions grows.
We want to know how the cost of common token actions scales with input size.
Analyze the time complexity of the following ERC-20 transfer function.
function transfer(address to, uint256 amount) public returns (bool) {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[to] += amount;
emit Transfer(msg.sender, to, amount);
return true;
}
This function moves tokens from one user to another by updating balances and emitting an event.
Look for loops or repeated steps inside the function.
- Primary operation: Access and update two entries in a mapping (balances).
- How many times: Exactly once per transfer call, no loops or recursion.
The function always does the same fixed number of steps regardless of 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 no matter how many users or tokens there are.
Time Complexity: O(1)
This means the transfer function takes the same amount of time no matter how many tokens or users exist.
[X] Wrong: "The transfer time grows as more users hold tokens because balances get bigger."
[OK] Correct: Each transfer only updates two specific balances directly, so the number of users does not affect the time.
Understanding that token transfers run in constant time helps you explain efficiency in blockchain operations clearly and confidently.
"What if the transfer function also iterated over all token holders to update some data? How would the time complexity change?"
Practice
ERC-20 standard in Ethereum?Solution
Step 1: Understand ERC-20 purpose
ERC-20 defines a common interface for fungible tokens to work uniformly.Step 2: Identify the correct purpose
This standard allows wallets and apps to interact with tokens easily by using the same functions.Final Answer:
To ensure tokens have a common set of functions for compatibility -> Option AQuick Check:
ERC-20 = Common token interface [OK]
- Confusing ERC-20 with NFT standards
- Thinking ERC-20 controls Ethereum network rules
- Assuming ERC-20 manages deployment costs
Solution
Step 1: Recall ERC-20 balance function
The standard definesbalanceOfas a view function returning a uint256 balance.Step 2: Match function signature
function balanceOf(address owner) external view returns (uint256); matches the exact signature: external view returns (uint256).Final Answer:
function balanceOf(address owner) external view returns (uint256); -> Option AQuick Check:
balanceOf = correct signature [OK]
- Using wrong function name like getBalance
- Missing view keyword for read-only function
- Returning bool instead of uint256
function transfer(address to, uint256 amount) public returns (bool) {
if (balances[msg.sender] < amount) {
return false;
}
balances[msg.sender] -= amount;
balances[to] += amount;
emit Transfer(msg.sender, to, amount);
return true;
}What will
transfer return if the sender has 50 tokens and tries to send 60 tokens?Solution
Step 1: Check sender balance condition
The function checks if sender's balance is less than amount; if yes, returns false.Step 2: Apply given values
Sender has 50 tokens but tries to send 60, so condition is true and function returns false.Final Answer:
false -> Option BQuick Check:
Insufficient balance returns false [OK]
- Assuming it throws error instead of returning false
- Thinking it returns true regardless
- Confusing return value with event emission
approve function snippet:function approve(address spender, uint256 amount) public returns (bool) {
allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}What is the common security issue with this implementation?
Solution
Step 1: Understand approve race condition
Directly setting allowance can cause race conditions if spender uses old and new allowance simultaneously.Step 2: Identify missing mitigation
Safe implementations require resetting allowance to zero before changing it to new value to avoid this issue.Final Answer:
It allows race condition by directly setting allowance -> Option CQuick Check:
approve race condition = direct allowance set [OK]
- Thinking missing zero address check is main issue
- Assuming Approval event is missing
- Believing return value is incorrect
transfer function correctly implements this?Solution
Step 1: Calculate fee and net transfer
Calculate 1% fee from amount, subtract it to get net amount to recipient.Step 2: Transfer fee and net amount correctly
Send fee to fee collector address and net amount to recipient to implement fee deduction.Final Answer:
Deduct 1% from amount, send fee to collector, send rest to recipient -> Option DQuick Check:
Fee deducted and sent correctly = Deduct 1% from amount, send fee to collector, send rest to recipient [OK]
- Adding fee on top of amount instead of deducting
- Sending full amount to recipient and fee separately from sender
- Splitting amount equally between recipient and fee collector
Ready to prove it?
Pass the test and this pattern moves unknown
