Development of Flash Loan Arbitrage Bot
A 0.3% price gap in WETH between Uniswap v3 and SushiSwap. On $500k borrowed through Aave flash loan, this is $1,500 before fees. After paying 0.09% flash loan fee ($450) and gas ($20-50 on Ethereum mainnet), net profit is around $1,000 per atomic transaction that either fully executes or reverts without capital loss. This atomicity is what makes flash loan arbitrage fundamentally different from classic trading.
Why "Simple" Arbitrage Doesn't Work
Gas Auction and MEV Competition
On the public mempool, you're not the only one seeing the price gap. MEV bots scan the mempool and frontrun profitable transactions—they set a higher gas price, their transaction enters the block first, the gap closes, your transaction reverts, gas burned.
Solution: submit via Flashbots eth_sendBundle. The transaction goes directly to the validator, bypassing public mempool. No frontrunning, no gas auction with bots. Flashbots takes a percentage of profit (miner tip), but it's predictable.
Alternatively, MEV Blocker or BuilderNet for wider coverage. On L2 (Arbitrum, Base), centralized sequencer reduces MEV risk but doesn't eliminate it—private mempools exist there too.
Sandwich Protection in Executor Contract
The contract received a flash loan, bought WETH on DEX A, needs to sell on DEX B. Between the two swaps is a window—theoretically a sandwich bot could interfere if the transaction is multi-step. In practice, for flash loan arbitrage everything executes in one transaction, so external sandwich is impossible. But amountOutMinimum on each swap is mandatory—otherwise sandwich within the same block via other transactions can shift the price of a pool slot.
Revert and Gas Loss
Flash loan reverts if you don't return debt + fee in the same transaction. If arbitrage logic fails, all gas burns. On Ethereum mainnet, a failed transaction costs $10-50. With high attempt frequency, this accumulates.
Optimization: pre-simulate before sending. eth_call with full calldata—the contract simulates for free, and we see success/revert before spending real gas. In production bots, this is mandatory: simulate → if success → send bundle.
How We Build the System
Components
Price scanner—off-chain service in TypeScript/viem, subscribed to Swap events on all tracked pools via WebSocket. On each event, recalculates spot price and compares against the pair matrix. Detected gap > threshold (accounting for all fees): signal for arbitrage.
Profit calculator—precise PnL with: flash loan fee (Aave v3: 0.09%, Balancer: 0%), gas at current block (via eth_gasPrice + EIP-1559 base fee), slippage of both swaps (via Quoter), multisig tip for Flashbots. If result is negative, don't send.
Executor contract—Solidity contract implementing IFlashLoanSimpleReceiver (Aave) or IFlashLoanRecipient (Balancer). Inside executeOperation / receiveFlashLoan—logic for two swaps and debt repayment.
| Flash Loan Provider | Fee | Limit | Features |
|---|---|---|---|
| Aave v3 | 0.09% | Pool liquidity | ERC-3156 compatible |
| Balancer v2 | 0% | Vault liquidity | No fee until tx end |
| Uniswap v3 | 0.05-1% | Pool liquidity | Flash swap, token returned to pool |
| dYdX | 0% | Limited assets | Solo Margin, harder integration |
Executor: What's Inside
function executeOperation(
address asset,
uint256 amount,
uint256 premium,
address initiator,
bytes calldata params
) external returns (bool) {
require(msg.sender == address(POOL), "Caller not Aave Pool");
require(initiator == address(this), "Initiator mismatch");
(address dexA, address dexB, uint256 amountOutMin) =
abi.decode(params, (address, address, uint256));
// swap on DEX A
uint256 received = _swapExact(dexA, asset, targetToken, amount, 0);
// swap back on DEX B
uint256 finalAmount = _swapExact(dexB, targetToken, asset, received, amountOutMin);
uint256 totalDebt = amount + premium;
require(finalAmount >= totalDebt, "Unprofitable");
IERC20(asset).approve(address(POOL), totalDebt);
return true;
}
Checks on msg.sender and initiator are mandatory. Without them, anyone can call executeOperation directly, passing arbitrary params, and drain tokens the contract holds in approval.
Monitoring and Maintenance
Arbitrage bots aren't set-and-forget systems. Gaps narrow as competitors multiply. Need a dashboard: attempts per hour, success percentage, average profit, gas spending. If success rate falls below 5%, time to rethink thresholds or add new pairs.
Work Process
Analytics (2-3 days). Determine target pairs, chains, DEXs. Analyze historical gap data via The Graph or Dune Analytics—estimate realistic profitability.
Development (1-2 weeks). Executor contract + off-chain scanner + Flashbots integration. Fork-tests on historical block with real gaps.
Testing. Run on testnet (Sepolia) with test flash loans. Then mainnet in simulation-only mode (only eth_call, no sending)—week of data collection and threshold calibration.
Production Deployment. Executor via Gnosis Safe (owner functions protected). Scripts for monitoring and auto-restart via PM2.
Timeline Estimates
Basic bot for one chain and two DEXs: 1-2 weeks. Multi-chain system with own price graph and Flashbots integration: 3-4 weeks.
Cost calculated after analyzing technical specification.







