Solana
Arbitrage
$124.50
Just now
Ethereum
Sandwich
$840.12
2s ago
BNB
Liquidator
$45.20
5s ago
Base
Arbitrage
$12.05
8s ago
Solana
Jito Bundle
$310.00
12s ago
Polygon
Arbitrage
$8.45
15s ago
Solana
Arbitrage
$124.50
Just now
Ethereum
Sandwich
$840.12
2s ago
BNB
Liquidator
$45.20
5s ago
Base
Arbitrage
$12.05
8s ago
Solana
Jito Bundle
$310.00
12s ago
Polygon
Arbitrage
$8.45
15s ago
TraderEvaluation stage⏱ 5 min read

Building Your First Atomic Arbitrage in 2026: Theory to First Fill

**Answer first** — An atomic arbitrage is a single transaction that buys an asset cheap on Pool A, sells it expensive on Pool B, and reverts entirely if the round-trip isn't profit

Atomic arbitrage flow showing two-pool price discrepancy captured in a single transaction
FR
FRB TeamMEV Specialists
Last updated
#Arbitrage#MEV#Tutorial#Beginner#Engineering

Answer first — An atomic arbitrage is a single transaction that buys an asset cheap on Pool A, sells it expensive on Pool B, and reverts entirely if the round-trip isn't profitable. In 2026, the easiest first one to build is a two-pool ETH/USDC arb on Base or Arbitrum — same asset pair, different DEXes (Uniswap V3 vs Aerodrome / SushiSwap), small price drift after a large swap on one pool. This article walks through it: pool math, calldata, slippage, simulation, and what your first live fill should actually look like.

If you don't yet know What is MEV, start there.

What Makes an Arbitrage "Atomic"

Three properties:

  1. Single transaction. Buy and sell are in the same tx, not two sequential ones.
  2. Conditional execution. A require(profit > 0, ...) revert if profit doesn't materialize.
  3. Flash-borrowable. Capital can be borrowed and repaid within the tx.

The atomicity is what protects you from execution risk. If anything goes wrong mid-tx, the whole thing reverts and you pay only gas, not principal.

The Theory in 60 Seconds

Two pools price the same asset slightly differently. After a large swap on Pool A pushes its price away from market, Pool B is cheaper. You buy on B, sell on A, capture the spread.

For two AMM pools using constant-product (x * y = k):

Effective_price_A = (reserve_y_A / reserve_x_A) × (1 - fee_A)
Effective_price_B = (reserve_y_B / reserve_x_B) × (1 - fee_B)

If Effective_price_A > Effective_price_B + slippage_buffer, an arb exists.

The optimal trade size is the size that equalizes the two pools' marginal prices. There's a closed-form solution, but you can use binary search or borrow Foundry's helpers.

Choosing Your First Pair

Pick a pair with:

  • High volume on both pools. Low-volume = stale prices but no fill depth.
  • Same fee tier on both pools (e.g. 5bps Uniswap V3 vs 5bps Aerodrome). Different fee tiers complicate math.
  • Direct pair, not multi-hop. Save multi-hop for later.
  • Liquid base asset. ETH/USDC, ETH/USDT, USDC/USDT. Not exotic.

Recommended starter pair on Base: WETH/USDC. Two pools to compare:

  • Aerodrome stable pool (fee 1bps)
  • Uniswap V3 0.05% tier (fee 5bps)

These have hundreds of millions in TVL and predictable spread behavior.

The Tools

You need:

  1. A WSS endpoint to your target chain (e.g. Base WSS via Alchemy or self-hosted).
  2. Foundry installed locally for simulation.
  3. A test wallet funded with $50–100 of ETH for gas + working capital.
  4. ABI for both DEXes' router contracts.

This entire setup runs on a laptop. We're not in production yet.

Step 1: Watch Spread

Subscribe to swaps on both pools and compute spread on every block:

js
const aero = new ethers.Contract(AERO_POOL, AERO_ABI, provider);
const uni  = new ethers.Contract(UNI_POOL, UNI_ABI, provider);

provider.on('block', async (n) => {
  const [r0a, r1a] = await aero.getReserves();
  const [r0u, r1u] = await uni.getReserves();
  // ... compute price each side, then spread
});

Watch for an hour. Most blocks: spread <1bp. Some blocks (after large swaps): spread 5–30bp. Note the frequency of profitable spreads.

Step 2: Profitability Threshold

Define "profitable" precisely. For a $5,000 working size:

gross_profit = trade_size × spread_bps / 10000
gas_cost     = gas_units × gas_price (in USD)
slippage     = trade_size × your_slippage_buffer
fees_paid    = trade_size × (fee_A + fee_B)
net_profit   = gross_profit − gas_cost − slippage − fees_paid

On Base, gas for a 2-pool arb tx is ~250–400k gas units. At typical 2026 gas price of ~0.001 gwei, that's $0.04–$0.10. Cheap.

For a $5,000 trade with 8bp spread:

  • Gross: $4.00
  • Gas: $0.08
  • Slippage buffer: $1.50 (3bp)
  • Fees: $3.00 (paid via pool slippage already)
  • Net: ~$2.40

That's a thin margin. Filter for spreads > 10bp on a $5k trade as your minimum.

Step 3: Calldata Construction

Two-pool arb calldata structure:

1. Approve router_B (if not pre-approved) - skip in production with infinite approvals
2. swap on router_B: USDC → WETH
3. swap on router_A: WETH → USDC
4. require(usdc_out > usdc_in + min_profit, "unprofitable")

For simplicity, use a dispatcher contract that does all four in one call. FRB Agent ships one (verified on every chain), or write your own minimal contract.

Minimal Solidity:

solidity
function executeArb(
    bytes calldata buyCalldata,
    bytes calldata sellCalldata,
    address tokenOut,
    uint256 minProfit
) external {
    uint256 startBalance = IERC20(tokenOut).balanceOf(address(this));
    (bool ok1, ) = router_B.call(buyCalldata);
    require(ok1, "buy failed");
    (bool ok2, ) = router_A.call(sellCalldata);
    require(ok2, "sell failed");
    uint256 endBalance = IERC20(tokenOut).balanceOf(address(this));
    require(endBalance >= startBalance + minProfit, "no profit");
}

Real implementations are harder (handle native ETH, multiple routers, callbacks for V3 pools). Treat the above as illustrative.

Step 4: Simulate Every Attempt

Before submitting, simulate the tx on a forked chain:

bash
anvil --fork-url $RPC_URL --fork-block-number latest
cast send --private-key $TEST_KEY $DISPATCHER \
    "executeArb(bytes,bytes,address,uint256)" \
    $BUY_CALLDATA $SELL_CALLDATA $WETH 1000000

If simulation succeeds with profit > min_profit, you're cleared to send. Skipping simulation is the #1 cause of reverts in beginner bots.

Step 5: Submit

For Base, submit to the public mempool (no PBS in 2026 yet on most L2s). Use a moderate priority fee to land in the next block:

js
const tx = await wallet.sendTransaction({
  to: DISPATCHER,
  data: dispatchCalldata,
  gasLimit: 500000,
  maxFeePerGas: ethers.parseUnits('0.0015', 'gwei'),
  maxPriorityFeePerGas: ethers.parseUnits('0.0005', 'gwei')
});
const receipt = await tx.wait();
console.log('Status:', receipt.status, 'Gas used:', receipt.gasUsed);

If receipt.status === 1, you landed it. Look at receipt.logs for the actual profit captured.

Step 6: Measure What Happened

Your first 20 attempts will mostly:

  • Revert (missed by another arber): 50–70%
  • Land but underwhelm vs simulation: 15–25%
  • Land profitably: 10–25%

That's normal. The ratio improves as you tune (lower latency, better signal filtering, smarter sizing).

What to log:

  • Spread observed at decision time
  • Spread observed at landing time
  • Predicted profit vs realized profit
  • Gas used vs estimated
  • Why each revert happened (Foundry traces help)

Step 7: Tighten the Loop

After 100 attempts, you'll see patterns:

  • Spreads above some threshold land more reliably
  • Certain hours have higher arb frequency
  • Specific competitors are faster than you in certain windows

Use the patterns to filter what you submit. Submitting fewer, higher-quality attempts beats spraying.

Common First-Bot Bugs

  • Approval missing: contract reverts on first call. Add infinite approval in deploy script.
  • Wrong pool fee tier: math says profit, real swap says loss because the math used 5bp pool but called 30bp pool.
  • Stale reserves: read reserves at block N, submit at block N+1 — state drifted. Re-read inside the contract or use callback-based pricing.
  • Slippage cap too tight: trades that would be slightly profitable revert. Calibrate to actual realized vs simulated.
  • Token decimals: USDC has 6, WETH has 18. Off-by-12 in math is a common bug.

What's Next After Two-Pool

Once two-pool arb runs cleanly:

  1. Three-pool triangular arb: USDC → WETH → DAI → USDC.
  2. Multi-DEX with pathfinding: dynamically pick which two of N pools to use.
  3. JIT liquidity: provide and pull LP around an incoming swap.
  4. Cross-chain arb: requires bridge cost modelling (advanced).

The skill stack compounds: pool math → calldata → simulation → latency → bidding. Two-pool atomic is the foundation.

FAQ

Do I have to write the smart contract myself?

For learning, yes. For production, FRB Agent ships verified dispatcher contracts on every supported chain. Use the built-ins in production; write your own in dev to understand them.

Why are most attempts unprofitable?

You're competing with bots that have lower latency, better signal filtering, and pre-approved liquidity. Beginners get the leftover spreads. That's fine — there are leftovers worth catching.

How much capital should I start with for arb?

$2k–5k. Below that, gas-to-capital is hostile. Above that, you can scale once tuned.

Is this strategy sandwich attack?

No. Two-pool arb between DEXes doesn't extract from a user's swap — it equalizes prices across pools. It's protocol-positive.

Can I run this on Ethereum L1 instead?

Technically yes, economically painful as a beginner. L1 gas of $10–50 per attempt eats most spreads at <$50k trade size. Start on L2.


This is an engineering tutorial. Deploy capital only after running on testnet or with paper-trade mode. Not financial advice.

Step after reading

Launch FRB dashboard

Connect your wallet, pair the node client with a 6-character PIN, and assign the contract mentioned above.

Need the signed build?

Download & verify FRB

Grab the latest installer, compare SHA‑256 to Releases, then follow the Safe start checklist.

Check Releases & SHA‑256

Related Articles

Further reading & tools

Discussion

No notes yet. Add the first observation, or share the link with your team on X (@MCFRB).

Leave a note
Notes are stored locally in your browser only.

Control the Pulse

Expand Your Execution

Maximize your edge by exploring the full FRB toolkit. From institutional-grade telemetry to ready-to-export strategy scripts.

CTA

Install FRB Agent

Download verified Windows binaries and check SHA-256.

CTA

Read Quick Start Docs

Share the 15-minute setup flow with ops & compliance.

CTA

Launch Control Panel

Pair node clients and monitor Ops Pulse in real-time.

Blog → App Bridge

Ready to deploy this strategy? Open the dashboard and monitor execution.

Ready to Evolve?

Take the Next Step

Whether you're verifying terminal security or launching your first bundle, the FRB journey starts here.

Recommended

Install FRB agent

Secure Windows build. Verified via SHA-256 for maximum integrity.

Recommended

Read Docs Quick Start

Master the setup in 15 minutes. From wallet pairing to first bundle.

Recommended

Launch /app dashboard

Monitor your Ops Pulse and manage transaction routes in real-time.