Build Your Own DeFi Arbitrage Bot with Flash Loans

Step‑by‑step tutorial covering smart‑contract development, flash‑loan sourcing, transaction routing, and profit extraction, featuring code snippets fr

Step‑by‑step tutorial covering smart‑contract development, flash‑loan sourcing, transaction routing, and profit extraction, featuring code snippets fr

Build Your Own DeFi Arbitrage Bot with Flash Loans

Author: Senior Crypto Analyst

---

Introduction

DeFi (Decentralized Finance) has reshaped capital markets by allowing anyone with an internet connection to access sophisticated financial instruments without a traditional intermediary. One of the most compelling opportunities in DeFi is crypto arbitrage, the practice of exploiting price differentials across multiple exchanges or liquidity pools. When arbitrage is executed via flash loans, traders can conduct large‑scale, capital‑intensive strategies without holding the required collateral upfront. This article provides a step‑by‑step guide to building a fully automated DeFi arbitrage bot that leverages flash loans, covers smart‑contract development, flash‑loan sourcing, transaction routing, and profit extraction, and references code patterns from the ExtropyIO open‑source repository.

By the end of the guide, you will understand the technical foundations, risk considerations, and operational best practices required to launch a production‑grade arbitrage bot. The knowledge presented here is intended for developers with intermediate Solidity skills and a solid grasp of Ethereum network fundamentals.

---

1. Foundations of DeFi Arbitrage

1.1 What Is Crypto Arbitrage?

Crypto arbitrage is the simultaneous purchase of an asset on a market where it trades at a lower price and the sale of the same asset on a market where it trades at a higher price. The arbitrageur captures the price spread as profit.

1.2 Types of Arbitrage Opportunities

| Type | Description | Typical Execution Time |

|------|-------------|------------------------|

| Spatial | Price difference across separate exchanges (e.g., Uniswap vs. SushiSwap). | Seconds to minutes |

| Triangular | Exploits three‑currency loops within a single DEX (e.g., ETH → DAI → USDC → ETH). | Sub‑second |

| Statistical | Uses historical price patterns and predictive models to anticipate temporary mispricings. | Minutes to hours |

| Cross‑Chain | Leverages price gaps between blockchains connected by bridges. | Minutes |

1.3 Why Flash Loans Enable Scalable Arbitrage

Flash loans allow the borrowing of unlimited capital for the duration of a single transaction, provided the loan is repaid within that transaction. The borrower pays a small protocol fee (typically 0.09 % on Aave v3) but does not need to supply collateral. This model removes the barrier of capital constraints, allowing an arbitrage bot to act on high‑volume opportunities that would otherwise be inaccessible.

1.4 Market Size and Statistical Outlook

According to DeFi Llama, the total value locked (TVL) in DeFi surpassed $90 billion in the second quarter of 2024. A significant portion of TVL resides in automated market makers (AMMs), which generate continuous price slippage that can be captured by arbitrageurs. Research from Messari indicates that arbitrage activity accounted for an estimated $12 billion in transaction volume across major DEXs in 2023. These data points demonstrate a robust environment for arbitrage bots.

---

2. Flash Loan Mechanics

2.1 Flash Loan Lifecycle

1. Borrow – The smart contract requests a loan from a lending protocol (e.g., Aave, dYdX).

2. Execute – The contract performs a series of swaps, arbitrage trades, or collateral operations.

3. Repay – The contract repays the principal plus the protocol fee before the transaction ends.

If the repayment condition fails, the entire transaction is reverted, leaving the blockchain state unchanged.

2.2 Common Flash Loan Providers

| Protocol | Chain | Maximum Loan | Fee |

|----------|-------|--------------|-----|

| Aave v3 | Ethereum, Optimism, Arbitrum | Unlimited (subject to liquidity) | 0.09 % |

| dYdX v4 | StarkNet, Ethereum | Unlimited | 0.05 % |

| Uniswap V3 Flash Swaps | Ethereum, Polygon | Unlimited (pool liquidity) | No explicit fee; pool charges spread |

2.3 Contract Interface Requirements

A flash‑loan borrower must implement the callback function defined by the lender. For Aave v3, the relevant interface is IFlashLoanSimpleReceiver. The function signature is:

`solidity

function executeOperation(

address asset,

uint256 amount,

uint256 premium,

address initiator,

bytes calldata params

) external returns (bool);

`

The contract must return true to signal successful execution. Any revert within executeOperation aborts the transaction.

---

3. Smart‑Contract Architecture

3.1 Core Modules

1. Loan Manager – Handles borrowing and repayment logic.

2. Arbitrage Engine – Calculates optimal trade routes and executes swaps.

3. Risk Guard – Validates slippage limits, gas price caps, and profit thresholds before proceeding.

3.2 Designing a Modular Contract

A modular design improves readability and facilitates future upgrades. Below is a high‑level diagram of the contract composition:

`

ArbBot (Main)

│

├─ LoanManager (inherits IFlashLoanSimpleReceiver)

│ └─ handleFlashLoan()

│

├─ ArbitrageEngine

│ └─ computeOptimalPath()

│ └─ executeSwaps()

│

└─ RiskGuard

└─ verifyProfit()

└─ enforceSlippage()

`

Each module resides in its own Solidity file, simplifying unit testing.

3.3 Example: LoanManager Implementation

`solidity

pragma solidity ^0.8.20;

import {IFlashLoanSimpleReceiver} from "@aave/core-v3/contracts/flashloan/interfaces/IFlashLoanSimpleReceiver.sol";

import {IPoolAddressesProvider} from "@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol";

contract LoanManager is IFlashLoanSimpleReceiver {

IPoolAddressesProvider public immutable provider;

constructor(IPoolAddressesProvider _provider) {

provider = _provider;

}

function initiateFlashLoan(

address asset,

uint256 amount,

bytes calldata params

) external {

address pool = provider.getPool();

IFlashLoanSimpleReceiver(pool).flashLoanSimple(

address(this),

asset,

amount,

params,

0

);

}

function executeOperation(

address asset,

uint256 amount,

uint256 premium,

address,

bytes calldata params

) external override returns (bool) {

// Delegate to arbitrage engine

(bool success, ) = address(this).call(

abi.encodeWithSignature("runArbitrage(address,uint256,uint256,bytes)", asset, amount, premium, params)

);

require(success, "Arbitrage execution failed");

// Repay loan + premium

uint256 totalDebt = amount + premium;

IERC20(asset).approve(msg.sender, totalDebt);

return true;

}

}

`

The code follows industry best practices: it uses immutable storage for the provider, checks the success of the arbitrage call, and approves the lender for exact repayment amount.

---

4. Sourcing Flash Loans

4.1 Selecting the Optimal Lender

The ideal flash‑loan provider depends on three criteria:

1. Liquidity – Larger pools increase the probability of full loan execution.

2. Fee Structure – Lower fees improve net profitability.

3. Network Congestion – Lenders on less congested layers (e.g., Optimism) may provide faster confirmations.

A comparative analysis of Aave v3 and dYdX v4 on Ethereum shows that Aave’s average fee of 0.09 % is marginally higher than dYdX’s 0.05 %, but Aave offers a broader set of assets, including stablecoins and wrapped tokens.

4.2 Accessing Lender APIs

Both Aave and dYdX expose on‑chain contracts that can be invoked directly from Solidity. The loan request is a single transaction call, which eliminates the need for off‑chain APIs. For off‑chain monitoring, developers can subscribe to the FlashLoan event emitted by the lender’s pool contract.

4.3 Example: Initiating a Flash Loan on Optimism

`solidity

function requestOptimismLoan(address asset, uint256 amount) external {

// Optimism uses the same Aave v3 deployment as Ethereum

address provider = 0xa97684ead0e402dC232d5A977953DF944a9e5B14; // Optimism PoolAddressesProvider

LoanManager loanManager = new LoanManager(IPoolAddressesProvider(provider));

loanManager.initiateFlashLoan(asset, amount, abi.encodePacked(msg.sender));

}

`

This snippet shows the deployment of a LoanManager contract specific to the Optimism network, leveraging the same Aave v3 core modules.

---

5. Transaction Routing and Gas Optimization

5.1 Determining the Optimal Swap Path

A decentralized exchange (DEX) router such as Uniswap V3 provides a quoteExactInputSingle function that returns the expected output amount for a given input amount. By querying multiple DEXs, the arbitrage engine can compare potential profits.

A typical routing algorithm executes the following steps:

1. Fetch price quotes from each target DEX for the asset pair.

2. Apply slippage tolerance (e.g., 0.5 %).

3. Subtract protocol fees (including flash‑loan premium).

4. Select the route with the highest net profit.

5.2 Gas Cost Considerations

On Ethereum, the average gas price in Q2 2024 was 22 gwei, with an average transaction consuming roughly 210,000 gas for a multi‑swap flash‑loan arbitrage. At an ETH price of $1,850, the gas cost equates to approximately $85 per transaction. Efficient routing can reduce gas consumption by up to 15 % by eliminating redundant token approvals and using permit signatures where supported.

5.3 Using the permit EIP‑2612 Standard

The permit function allows token approvals via a signed message instead of an on‑chain transaction. Implementing permit can decrease the number of required internal calls, saving gas. An example of a permit call for USDC is:

`solidity

function permitUSDC(

address token,

address spender,

uint256 value,

uint256 deadline,

uint8 v,

bytes32 r,

bytes32 s

) internal {

IERC20Permit(token).permit(msg.sender, spender, value, deadline, v, r, s);

}

`

5.4 Example: Routing Logic (Pseudo‑Code)

`solidity

function computeOptimalPath(

address tokenIn,

address tokenOut,

uint256 amountIn

) internal view returns (bytes memory bestPath, uint256 bestProfit) {

uint256 bestNet = 0;

bytes memory candidate;

// Query Uniswap V3

uint256 uniOut = IUniswapV3Router(routerUni).quoteExactInputSingle(

tokenIn, tokenOut, 3000, amountIn, 0

);

uint256 uniNet = uniOut - flashLoanFee - routerFee;

if (uniNet > bestNet) {

bestNet = uniNet;

candidate = abi.encodePacked

ArbitrageRadar PRO on the App Store · arbitrageradarpro.com

Related guides

All guides · Coins · Exchanges

ArbitrageRadar PRO on the App Store · arbitrageradarpro.com