- name:
- front-running-attacks
- description:
- Commit function accepts a raw value type instead of a hash - the committed value is visible in transaction calldata, enabling front-running before reveal phase
- category:
- vulnerability-pattern
- pattern_category:
- front-running
- - regex:
- function\s+commit\s*\(\s*(uint\d*|int\d*|address|bool|string)\s
- severity:
- Medium
- confidence:
- Medium
- swc:
- SWC-120
Front-Running and MEV Attack Patterns
Overview
Front-running attacks occur when adversaries observe pending transactions and reorder, insert, or censor their own transactions to extract value. In Ethereum-style public mempools, this behavior is often automated through searchers, builders, and relay infrastructure. If contract logic assumes fair ordering, it will fail under adversarial execution.
MEV exposure is not limited to AMM swaps. Any function where outcome depends on timing, ordering, or visible intent can be exploited: auctions, liquidations, reward claims, randomness games, and commit-reveal schemes. Attackers exploit predictability, not just missing access control.
Security review must model mempool visibility and builder-level ordering power as default assumptions. A safe design either removes ordering sensitivity, bounds downside with strict parameters, or hides actionable information until execution is finalized.
Key Attack Vectors
- Sandwich attacks against swaps that set
amountOutMin to zero or near-zero values.
- Deadline misuse where
deadline == block.timestamp gives no practical expiration window.
- Backrun liquidation opportunities caused by stale off-chain quote assumptions.
- Randomness generation from
block.timestamp, block.number, or block.prevrandao.
- Weak commit-reveal implementations that publish raw secrets during commit phase.
- Reveal functions without strict phase windows, enabling selective reveal timing.
- Signature-based order flows missing nonce/domain separation and replay protections.
- Oracle update races where reads are exploitable between update and settlement.
Typical Sandwich Flow
- Victim submits swap with permissive slippage.
- Searcher detects intent in mempool.
- Searcher submits frontrun trade to move pool price against victim.
- Victim executes at degraded price.
- Searcher backruns in opposite direction and captures spread.
- Net value is extracted from victim through slippage.
Typical Commit-Reveal Failure
- User calls
commit(value) with plaintext value.
- Adversary reads calldata before inclusion.
- Adversary submits matching or superior action first.
- Reveal phase no longer offers secrecy advantage.
- Game fairness assumptions break and funds are misallocated.
Detection Heuristics
Swap Safety Checks
- Flag any swap invocation where minimum output argument is hardcoded to
0.
- Verify slippage bounds are user-defined and validated on-chain.
- Confirm quote freshness constraints and max price impact checks exist.
- Detect missing private-orderflow or intent-protection pathways for high-value operations.
Deadline Robustness
- Detect
deadline = block.timestamp assignments in routers and adapters.
- Ensure deadlines are passed from user context and bounded to short windows.
- Check that stale transactions fail safely after expiration.
- Verify signatures include explicit expiry fields and are enforced.
Randomness Integrity
- Flag entropy derived from
block.timestamp, block.number, blockhash, prevrandao alone.
- Check whether attacker can influence inclusion timing or validator context.
- Require verifiable randomness (VRF) or delayed commit-based entropy mixing.
- Review payout and settlement logic for timing-dependent outcomes.
Commit-Reveal Correctness
- Commit input should be
bytes32 commitment, not raw values.
- Commitment must bind
(value, salt, sender, nonce, domain).
- Reveal must verify preimage and enforce strict phase ordering.
- Unrevealed commitments should have explicit timeout and penalty semantics.
Concrete Code Smells
router.swapExactTokensForTokens(
amountIn,
0, // unlimited slippage
path,
msg.sender,
block.timestamp // ineffective deadline
);
function random() internal view returns (uint256) {
return uint256(keccak256(abi.encodePacked(block.timestamp, msg.sender)));
}
function commit(uint256 guess) external {
commits[msg.sender] = guess; // plaintext commit
}
Audit Questions
- If an attacker sees this transaction 5 seconds early, can they profitably reorder around it?
- Is every user-protective parameter set by caller input rather than contract defaults?
- Does reveal logic preserve secrecy until reveal, or leak value during commit?
- Does protocol use secure randomness when value transfer depends on random outcomes?
Prevention
Slippage and Execution Controls
- Require non-zero
amountOutMin derived from bounded slippage tolerance.
- Validate path and pool depth to avoid toxic route execution.
- Add max price impact constraints at execution time.
- Offer private mempool routing for sensitive operations when practical.
Deadline and Signature Hygiene
- Accept user-provided deadlines and enforce short expiry windows.
- Include nonce, chain ID, and verifying contract in signed payloads.
- Reject signatures that are expired or already used.
- Do not use current block timestamp as the sole deadline source.
Secure Randomness
- Use Chainlink VRF or equivalent verifiable source for high-value randomness.
- If VRF is unavailable, use commit-reveal with delayed settlement and slashable non-reveal behavior.
- Mix entropy with domain separators and sequence numbers.
- Keep payouts decoupled from miner-influenceable inputs.
Correct Commit-Reveal Pattern
function commit(bytes32 commitment) external {
require(commitPhaseOpen(), "Commit closed");
commits[msg.sender] = commitment;
}
function reveal(uint256 value, bytes32 salt) external {
require(revealPhaseOpen(), "Reveal closed");
bytes32 expected = keccak256(abi.encodePacked(value, salt, msg.sender, nonce[msg.sender]));
require(commits[msg.sender] == expected, "Invalid reveal");
nonce[msg.sender] += 1;
_settle(value);
}
Operational Defenses
- Monitor abnormal slippage and repeated same-block sandwiches.
- Simulate adversarial ordering in pre-deployment tests.
- Publish best-practice transaction settings in frontend UX.
- Use circuit breakers for extreme MEV conditions during volatility spikes.
Real-World Examples
AMM Sandwiching (Recurring Across DEXes)
- Pattern: swaps with loose or zero slippage controls.
- Impact: users receive significantly worse execution than quoted.
- Lesson: slippage bounds are mandatory user protection, not optional convenience.
Fairness Breaks in Weak Commit-Reveal Games
- Pattern: commit phase leaks values in calldata.
- Impact: adversaries preempt outcomes before reveal.
- Lesson: commitments must be opaque hashes with salts and sender binding.
Randomness Exploits in On-Chain Games
- Pattern: entropy from miner-influenceable block variables.
- Impact: validators/searchers skew outcomes for profit.
- Lesson: use verifiable randomness for value-bearing random outcomes.
Pattern-to-Impact Mapping
missing-slippage-protection -> sandwich extraction and toxic execution.
missing-deadline -> delayed execution under changed market conditions.
predictable-randomness -> manipulable game or reward outcomes.
commit-reveal-weakness -> pre-reveal information leakage and front-run wins.
References
- SWC-114 (Transaction order dependence): https://swcregistry.io/docs/SWC-114
- SWC-120 (Weak randomness): https://swcregistry.io/docs/SWC-120
- Flash Boys 2.0 paper: https://arxiv.org/abs/1904.05234
- Paradigm MEV resources: https://www.paradigm.xyz/
- Ethereum PBS and MEV-Boost research: https://github.com/flashbots/mev-boost
- Chainlink VRF docs: https://docs.chain.link/vrf
- Uniswap docs on slippage and execution: https://docs.uniswap.org/