Gas optimization for L2 in Blockchain / Solidity - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
When working with Layer 2 (L2) blockchain solutions, gas optimization helps reduce transaction costs.
We want to understand how the cost of operations grows as we handle more data or users.
Analyze the time complexity of the following L2 gas optimization snippet.
function batchTransfer(address[] memory recipients, uint256 amount) public {
for (uint i = 0; i < recipients.length; i++) {
_transfer(msg.sender, recipients[i], amount);
}
}
This code sends tokens to many recipients in one batch to save gas compared to individual transfers.
Look for loops or repeated actions that affect gas cost.
- Primary operation: The for-loop that calls
_transferfor each recipient. - How many times: Once for each recipient in the
recipientsarray.
As the number of recipients grows, the number of transfers grows too.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 transfers |
| 100 | 100 transfers |
| 1000 | 1000 transfers |
Pattern observation: The work grows directly with the number of recipients.
Time Complexity: O(n)
This means the gas cost increases linearly as you add more recipients.
[X] Wrong: "Batching transfers makes gas cost constant no matter how many recipients there are."
[OK] Correct: Each transfer still uses gas, so total cost grows with the number of recipients, even if batching saves some overhead.
Understanding how gas cost scales with batch size shows you can write efficient smart contracts that save users money.
"What if we replaced the for-loop with a single call that transfers to all recipients at once? How would the time complexity change?"
Practice
Solution
Step 1: Understand calldata vs memory
Calldata is cheaper than memory because it is read-only and does not require copying data.Step 2: Identify gas saving method
Using calldata for function inputs reduces gas compared to memory or storage.Final Answer:
Using calldata instead of memory for function inputs -> Option DQuick Check:
Calldata is cheaper than memory [OK]
- Thinking increasing block size reduces gas
- Assuming more storage variables save gas
- Using loops without optimization
Solution
Step 1: Recall parameter data location keywords
Solidity allows memory, storage, or calldata for reference types in parameters.Step 2: Identify calldata usage
Calldata is specified explicitly asstring calldatafor external functions to save gas.Final Answer:
function foo(string calldata data) external {} -> Option BQuick Check:
Calldata keyword used correctly [OK]
- Using memory instead of calldata for external inputs
- Omitting data location keyword
- Using storage incorrectly in parameters
unchecked math in Solidity on L2 compared to normal math?Solution
Step 1: Understand unchecked math
Unchecked math skips overflow and underflow checks, saving gas.Step 2: Compare gas costs
Skipping checks reduces gas cost compared to normal safe math operations.Final Answer:
Gas cost decreases because overflow checks are skipped -> Option AQuick Check:
Unchecked math saves gas by skipping checks [OK]
- Assuming unchecked math adds overhead
- Believing gas cost is unchanged
- Ignoring overflow risks
uint256 public count;
function increment() external {
count = count + 1;
}Solution
Step 1: Identify gas cost in arithmetic
Normal addition includes overflow checks increasing gas.Step 2: Suggest unchecked usage
Wrapping increment inunchecked { count += 1; }saves gas by skipping checks.Final Answer:
Missing unchecked block for increment -> Option AQuick Check:
Unchecked block reduces gas for safe increments [OK]
- Thinking public visibility affects gas here
- Confusing external with view function
- Assuming code is already optimized
Solution
Step 1: Understand storage slot packing
Multiple small variables like uint8 can fit into one 256-bit slot, saving gas.Step 2: Compare storage strategies
Separating variables wastes slots; dynamic arrays add overhead; calldata usage unrelated here.Final Answer:
Pack multiple uint8 variables into a single uint256 storage slot -> Option CQuick Check:
Storage packing reduces gas by slot sharing [OK]
- Using separate slots wastes gas
- Overusing dynamic arrays increases cost
- Ignoring calldata benefits in storage
