Skip to content

Pablosinyores/flash-loan-executor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 

Repository files navigation

Flash Loan Arbitrage Executor

A Solidity smart contract that executes atomic arbitrage trades using Aave V3 flash loans across Uniswap V2 and SushiSwap — requiring zero upfront capital.

How It Works

1. Owner calls requestFlashLoan(DAI, 100k, WETH, uniswapRouter, sushiRouter)
2. Aave V3 sends 100k DAI to the contract, triggers executeOperation() callback
3. Swap DAI -> WETH on Uniswap V2 (where WETH is cheaper)
4. Swap WETH -> DAI on SushiSwap (where WETH is more expensive)
5. Repay Aave: 100k DAI + 0.05% fee
6. Remaining DAI = profit, held in contract
7. Owner calls withdraw() to collect

The entire flow executes atomically in a single transaction. If the trade is not profitable after fees, the transaction reverts and no funds are lost.

Architecture

src/
├── FlashLoanArbitrage.sol              # Main contract
└── interfaces/
    ├── IERC20.sol                      # Standard ERC20
    ├── IFlashLoanSimpleReceiver.sol    # Aave V3 callback interface
    ├── IPool.sol                       # Aave V3 pool (flashLoanSimple)
    ├── IPoolAddressesProvider.sol      # Aave V3 address resolver
    └── IUniswapV2Router02.sol          # Shared by Uniswap V2 & SushiSwap
test/
└── FlashLoanArbitrage.t.sol            # Fork tests (6 test cases)
script/
└── DeployFlashLoanArbitrage.s.sol      # Deployment script

Contract API

requestFlashLoan(tokenBorrow, amount, tokenIntermediate, buyDex, sellDex)

Owner-only entry point. Initiates a flash loan from Aave V3 and executes a two-leg swap.

Parameter Description
tokenBorrow Token to borrow and repay (e.g., DAI)
amount Amount to borrow
tokenIntermediate Token to swap through (e.g., WETH)
buyDex Router address where tokenBorrow -> tokenIntermediate is cheaper
sellDex Router address where tokenIntermediate -> tokenBorrow is more expensive

withdraw(token) / withdrawETH()

Owner-only. Transfers the contract's full balance of the specified token (or ETH) to the owner.

executeOperation(asset, amount, premium, initiator, params)

Aave V3 callback. Cannot be called directly — only the Aave Pool can invoke this. Validates the caller and initiator, performs both swaps, checks profitability, and approves repayment.

Mainnet Addresses

Contract Address
Aave V3 PoolAddressesProvider 0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e
Uniswap V2 Router 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
SushiSwap Router 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F
WETH 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
DAI 0x6B175474E89094C44Da98b954EedeAC495271d0F

Prerequisites

  • Foundry (forge, cast)
  • An Ethereum mainnet archive RPC URL (required for fork testing)

Setup

git clone <repo-url> && cd flash-loan-executor
forge install
cp .env.example .env
# Edit .env with your RPC URL and keys

Build

forge build

Test

Tests run against a mainnet fork pinned to block 18,000,000 (~Sep 2023).

source .env
forge test -vvv
Test What it verifies
test_successfulArbitrage_DAI_WETH Full flash loan + two-swap flow produces profit
test_revert_unprofitableArbitrage Reverts when no price discrepancy exists
test_revert_onlyOwnerCanRequestFlashLoan Non-owner cannot trigger flash loan
test_revert_onlyOwnerCanWithdraw Non-owner cannot withdraw
test_withdrawAfterProfit Owner can withdraw tokens from contract
test_revert_executeOperationOnlyPool Direct calls to executeOperation revert

Deploy

source .env
forge script script/DeployFlashLoanArbitrage.s.sol:DeployFlashLoanArbitrage \
  --rpc-url $MAINNET_RPC_URL \
  --broadcast \
  --verify

Security Considerations

This contract is unaudited and intended for educational purposes. Known risks:

  • Slippage: amountOutMin is set to 0 on both swaps. Profitability is enforced atomically after both swaps complete, but individual legs are exposed to sandwich attacks.
  • Single owner: No multisig or timelock. The owner address has full control over flash loan execution and fund withdrawal.
  • Max approvals: _approveIfNeeded grants type(uint256).max allowance to DEX routers and the Aave Pool on first use.
  • MEV exposure: Arbitrage transactions on mainnet are visible in the mempool and can be frontrun by MEV searchers.

Stack

Foundry | Solidity 0.8.20 | Aave V3 | Uniswap V2 | SushiSwap | Ethereum Mainnet

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors