Front-running awareness in Blockchain / Solidity - Time & Space Complexity
When dealing with blockchain transactions, it is important to understand how the time to process transactions can grow as more users interact with the network.
We want to see how the cost of detecting front-running attempts changes as the number of transactions increases.
Analyze the time complexity of the following code snippet.
function detectFrontRunning(pendingTxs, newTx) {
for (let tx of pendingTxs) {
if (tx.sender === newTx.sender) continue;
if (tx.target === newTx.target && tx.value < newTx.value) {
return true; // Front-running detected
}
}
return false;
}
This function checks if a new transaction is being front-run by scanning all pending transactions for conflicts.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through all pending transactions.
- How many times: Once for each pending transaction in the list.
As the number of pending transactions grows, the function checks each one to find front-running.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 checks |
| 100 | 100 checks |
| 1000 | 1000 checks |
Pattern observation: The number of checks grows directly with the number of pending transactions.
Time Complexity: O(n)
This means the time to detect front-running grows linearly as more transactions are pending.
[X] Wrong: "Checking just a few transactions is enough to detect front-running quickly."
[OK] Correct: Front-running can happen with any pending transaction, so skipping checks risks missing it.
Understanding how the cost of scanning transactions grows helps you design better blockchain tools and shows you can think about performance in real systems.
"What if we indexed pending transactions by target address? How would the time complexity change?"
Practice
Solution
Step 1: Understand front-running concept
Front-running happens when someone notices your transaction before it is confirmed and tries to act first to benefit.Step 2: Identify correct description
Someone sees your pending transaction and acts before it to gain advantage correctly describes this behavior, while others describe unrelated blockchain actions.Final Answer:
Someone sees your pending transaction and acts before it to gain advantage -> Option BQuick Check:
Front-running = Acting before your transaction [OK]
- Confusing front-running with low gas fees
- Thinking front-running is miner censorship
- Mixing front-running with wallet automation
Solution
Step 1: Review front-running prevention methods
Commit-reveal schemes hide transaction details until a later phase, preventing others from copying or front-running.Step 2: Evaluate options
Use commit-reveal scheme to hide transaction details until reveal phase correctly uses commit-reveal. Options B, C, and D either increase risk or are ineffective.Final Answer:
Use commit-reveal scheme to hide transaction details until reveal phase -> Option AQuick Check:
Commit-reveal = Prevent front-running [OK]
- Thinking zero gas fees hide transactions
- Believing network congestion prevents front-running
- Using public mempool to announce transactions early
queue = [tx1, tx2, tx3]
miner_orders = [tx3, tx1, tx2]
for tx in miner_orders:
process(tx)
Which transaction is most likely to be front-run if tx1 was broadcast first?Solution
Step 1: Analyze transaction broadcast and miner order
tx1 was broadcast first, but miner processes tx3 before tx1.Step 2: Identify front-run transaction
Since tx3 is processed before tx1, tx3 front-runs tx1.Final Answer:
tx3 -> Option AQuick Check:
Miner order front-runs broadcast order = tx3 [OK]
- Assuming broadcast order equals processing order
- Ignoring miner transaction reordering
- Thinking no front-running if all txs are in queue
mapping(address => bytes32) public commitments;
function commit(bytes32 hash) public {
commitments[msg.sender] = hash;
}
function reveal(uint256 value, string memory secret) public {
require(commitments[msg.sender] == keccak256(abi.encodePacked(value, secret)), "Invalid reveal");
// process value
}
What is the bug that could allow front-running here?Solution
Step 1: Understand commit-reveal logic
Commit stores a hash, reveal checks hash matches value and secret.Step 2: Identify bug in commit function
Commit overwrites previous commitments without expiration, allowing replay or front-running by reusing old commits.Final Answer:
The commit function overwrites previous commitments without expiration -> Option CQuick Check:
Overwriting commits = front-running risk [OK]
- Thinking reveal lacks ownership check
- Assuming encoding is incorrect
- Believing secret is revealed too early
Solution
Step 1: Evaluate front-running prevention techniques
Commit-reveal hides order details until reveal, reducing front-running. Paying higher gas fees can prioritize transactions.Step 2: Assess options for DEX design
Use commit-reveal for order submission and allow users to pay higher gas fees for priority combines commit-reveal and gas fee priority, effectively reducing front-running. Others either increase risk or are impractical.Final Answer:
Use commit-reveal for order submission and allow users to pay higher gas fees for priority -> Option DQuick Check:
Commit-reveal + gas fees = best front-running defense [OK]
- Trusting miners to order fairly without protection
- Restricting orders to trusted addresses limits decentralization
- Using zero gas fees removes transaction priority
Ready to prove it?
Pass the test and this pattern moves unknown
