DEX Trading Bot Development for Base
Base is an OP Stack L2 from Coinbase, launched August 2023. In first year became one of top-3 L2s by TVL and active addresses. For trading bots Base is interesting for three reasons: low gas (50–100x cheaper than mainnet), growing DEX liquidity on Aerodrome and Uniswap V3, and sequencer specifics different from Ethereum.
DEX ecosystem on Base
Key platforms for integration:
| DEX | Model | Volume (2024) | Features |
|---|---|---|---|
| Aerodrome Finance | ve(3,3) AMM + CLOB | $1B+ / day | Velodrome fork, native Base DEX |
| Uniswap V3 | Concentrated liquidity | $500M+ / day | Standard V3, same contracts as mainnet |
| BaseSwap | Fork Uniswap V2 | $50M / day | Lower liquidity |
| SushiSwap | V2 + Trident | $20M / day | Multi-chain, cross-DEX arbitrage |
Aerodrome — priority for deep integration: 60%+ of Base DEX volume goes through it.
Aerodrome: architecture important for bots
Aerodrome inherits Velodrome V2 architecture with two pool types:
Volatile pools (Pool.sol): standard x*y=k formula. Suits uncorrelated pairs (ETH/USDC, cbBTC/USDC).
Stable pools (Pool.sol with stable=true): curve x³y + y³x = k — optimized for similar-price assets (USDC/USDT, cbETH/wstETH). Important: for stable pools getAmountOut() gives different result at same inputs.
// Aerodrome Router ABI
const AERODROME_ROUTER = '0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43'
const routes = [{
from: WETH_ADDRESS,
to: USDC_ADDRESS,
stable: false, // For volatile pair
factory: AERODROME_FACTORY
}]
const amounts = await aerodromeRouter.getAmountsOut(amountIn, routes)
Common developer mistake from EVM background: use stable: false for all pairs. For USDC/USDbC pair this gives 5–10% worse calculated amountOut due to wrong curve.
ve(3,3) and epoch rewards
Aerodrome uses veAERO (locked voting tokens) to direct emissions to pools. For arbitrage bot this matters indirectly: high-emission pools attract more LP, have less slippage. Tracking votes and emissions helps predict where deep liquidity appears.
Sequencer specifics on Base
Base uses centralized sequencer managed by Coinbase. For bots this fundamentally changes MEV landscape:
- No public mempool in Ethereum sense. Sequencer publishes transactions atomically.
- Classic sandwich attacks via frontrunning practically impossible.
- DEX ↔ DEX arbitrage on Base works well: no flashbots bundle competition in same form.
- Latency to sequencer critical: us-east-1 server (AWS) or co-location in San Francisco (closer to Coinbase) gives edge.
Send transactions directly to https://mainnet.base.org RPC or via Alchemy/Infura Base endpoints. For min latency — own node with op-geth or Coinbase direct endpoint (via partnership).
Arbitrage strategy: Base inter-protocol
Most accessible and stable MEV on Base — arbitrage between DEXs:
Aerodrome vs Uniswap V3: same pair (ETH/USDC) trades on two venues with different prices due to async LP behavior.
Stablecoin arbitrage: USDC vs USDbC (bridged USDC) vs axlUSDC — often trade at slight discount/premium on different pools.
cbETH / wstETH arbitrage: ETH derivative assets, price pegged to ETH via exchange rate. On deviation from fair value — arbitrage opportunity.
Basic bot cycle:
async function checkArbitrage(tokenA: Address, tokenB: Address) {
// Parallel price request from two DEX
const [aeroPrice, uniPrice] = await Promise.all([
getAerodromePrice(tokenA, tokenB, amountIn),
getUniswapV3Price(tokenA, tokenB, amountIn)
])
const priceDiff = Math.abs(aeroPrice - uniPrice) / Math.min(aeroPrice, uniPrice)
if (priceDiff > MIN_PROFIT_THRESHOLD) {
const gasEstimate = await estimateArbitrageGas(...)
const gasCostUSD = gasEstimate * gasPrice * ethPrice
const grossProfit = calculateProfit(aeroPrice, uniPrice, amountIn)
if (grossProfit > gasCostUSD * 1.5) { // Minimum 1.5x coverage
await executeArbitrage(...)
}
}
}
Atomic arbitrage via flash loan
Aave V3 flash loans available on Base (contract deployed). Atomic arbitrage: borrow flash loan → buy cheaper → sell expensive → return flash loan + fee (0.09%).
Advantage: no capital needed for arbitrage. Flash loan fee sets minimum profitability — price diff must be > 0.09% + gas.
contract BaseArbitrageBot is IFlashLoanSimpleReceiver {
function executeArbitrage(address token, uint256 amount, bytes calldata params) external {
// Request flash loan
POOL.flashLoanSimple(address(this), token, amount, params, 0);
}
function executeOperation(
address asset, uint256 amount, uint256 premium,
address, bytes calldata params
) external override returns (bool) {
(address dexA, address dexB, bytes memory swapDataA, bytes memory swapDataB)
= abi.decode(params, (address, address, bytes, bytes));
// Buy on dexA (cheaper)
IERC20(asset).approve(dexA, amount);
(bool successA,) = dexA.call(swapDataA);
require(successA, "Swap A failed");
// Sell on dexB (expensive)
uint256 received = IERC20(outputToken).balanceOf(address(this));
IERC20(outputToken).approve(dexB, received);
(bool successB,) = dexB.call(swapDataB);
require(successB, "Swap B failed");
// Return flash loan + premium
uint256 repayAmount = amount + premium;
IERC20(asset).approve(address(POOL), repayAmount);
return true;
}
}
Contract is minimalist. No storage state — everything via calldata and events.
Monitoring and risk management
Price deviation alerts: if DEX price deviation exceeds 2% — potential anomaly (manipulation, oracle bug). Bot should halt until clarified.
Gas price tracking: Base gas unstable under high load. Bot must check eth_gasPrice and set maxFeePerGas dynamically. Hard gas price limit — above threshold arbitrage uninteresting.
Slippage on large positions: getAmountsOut for amount X doesn't account for price shift during execution. For large swaps need simulation with price impact — or split into smaller transactions.
Dead man's switch: if bot made no transactions for N minutes despite opportunities — alert to Telegram/Discord. Possible: node down, no gas balance, unexpected revert.
Development stack
Bot: TypeScript + viem (better than ethers.js for Base due to EIP-1559 type support). Bull (Redis-backed queue) for transaction queue management. Prometheus + Grafana for metrics.
Contracts: Solidity 0.8.24 + Foundry. Fork test on Base mainnet via forge test --fork-url https://mainnet.base.org. Foundry supports Base as target network.
Bot deploy: Docker on AWS EC2 (us-east-1) or Fly.io for simplicity, with auto-restart via systemd/Supervisor.
Working process
Research (2–3 days). Analyze MEV opportunities on Base via Dune Analytics, assess volumes and competition.
Development (1–2 weeks). Aerodrome and Uniswap V3 integration, arbitrage engine, flash loan contract, monitoring.
Testing (3–5 days). Backtest on Base historical data, paper trading in fork tests.
Launch. Deploy with small amounts → monitor performance → scale.







