Skip to content

propeller-heads/atomic-searcher

Repository files navigation

Atomic Searcher Showcase

⚠️ Notice: This is entirely vibed by a mediocre engineer who didn't even read the code. Treat it accordingly. (Product VibeCoder)

Autonomous cyclic arbitrage searcher built on Fynd's market data infrastructure.

Based on Janos Tapolcai's simulation-based Bellman-Ford arbitrage searcher.

What it does

Unlike Fynd's solver (which finds A-to-B routes for incoming orders), the atomic searcher proactively scans for profitable arbitrage cycles:

WETH -> Token_1 -> Token_2 -> ... -> WETH

If it ends up with more WETH than it started with (after gas), the cycle is profitable.

Algorithm

  1. Subscribe to Tycho market updates via Fynd's TychoFeed
  2. Extract subgraph around WETH (BFS to max_hops depth)
  3. Bellman-Ford cycle detection: Layered BF relaxation with SPFA optimization, calling get_amount_out() on actual pool simulations. After relaxation, check all edges pointing back to the source for cycles where amount_out > amount_in
  4. Golden section search: For each candidate cycle, optimize the input amount to maximize profit = amount_out - amount_in - gas_cost
  5. Log results: Print all cycles with path, optimal amount, profit, and gas cost

Solver vs Searcher

Fynd's solver Atomic Searcher
Trigger External order (token_in, token_out, amount) Autonomous, every block
Objective Maximize amount_out - gas for A to B Maximize amount_out - amount_in - gas for A to A
Input amount Fixed (from order) Optimized via golden section search
Output Single best route All profitable cycles

Usage

# Set your Tycho API key (must have beta-feed access)
export TYCHO_API_KEY="your-key"

# Run with defaults (Ethereum, WETH, 4 hops, 0.001 ETH seed)
cargo run --release

# Customize
cargo run --release -- \
  --chain ethereum \
  --tycho-url tycho-beta.propellerheads.xyz \
  --protocols uniswap_v2,uniswap_v3,sushiswap_v2 \
  --max-hops 4 \
  --seed-eth 1.0 \
  --min-tvl 10.0

# Verbose logging
RUST_LOG=atomic_searcher=debug,fynd=info cargo run --release

Output

INFO  Starting atomic searcher chain=Ethereum source_token=c02a...6cc2 max_hops=4
INFO  Initial sync complete, starting search block=21234567 nodes=1842 edges=9234
INFO  block search complete block=21234568 candidates=3 profitable=1 time_ms=12
INFO  [PROFITABLE] #0: c02a.. -> 6b17.. -> c02a.. | optimal_in: 0.4200 ETH | net_profit: 0.000142 ETH | gas: 0.003200 ETH | hops: 3
INFO  [unprofitable] #1: c02a.. -> a0b8.. -> c02a.. | optimal_in: 0.1500 ETH | net_profit: -0.001200 ETH | gas: 0.004100 ETH | hops: 2

Architecture

src/
  main.rs              Entry point, CLI, Tycho feed, per-block search loop
  cycle_detector.rs    Modified Bellman-Ford for cycle detection
  amount_optimizer.rs  Golden section search for optimal trade size
  executor.rs          Encode / simulate / submit cycles (all execution modes)
  flash_loan.rs        Flash-strategy selection and FlashArbExecutor calldata
  types.rs             CycleCandidate, EvaluatedCycle, ExecutionMode, ...
contracts/
  FlashArbExecutor.sol Flash-loan executor contract (UniV2 flash swap + Balancer flash loan)
test/                  Foundry tests for FlashArbExecutor

The binary reuses Fynd library components (TychoFeed, SharedMarketData, PetgraphStableDiGraphManager) but implements its own search loop since it is not responding to external orders. Execution (optional, off by default) is encoded via tycho-execution and submitted either directly or through the flash-loan contract.

References

Limitations

This is a showcase/educational tool, not production MEV software.

  • Execution is opt-in and off by default (--execution-mode log-only). Modes range from simulate through public-mempool, Flashbots-protected, and flash-loan execution. See GUIDE.md §4.
  • No cycle merging (shared-edge gas optimization, planned as follow-up)
  • No MEV-Share auction integration (the execute-protected mode uses Flashbots Protect, a private mempool, but does not bid in MEV-Share)
  • Single-block horizon: no state prediction or multi-block strategies
  • In current saturated markets, profitable cycles are rare (see Tapolcai et al., FC 2026)

Proven on mainnet

The full pipeline has been exercised end to end with real Ethereum mainnet transactions (deliberately tiny, net-negative-after-gas trades run with --force-execute):

Path Transaction Result
execute-public swap 0xcc0621f0…d151ce Success. Cyclic arb settled via TychoRouter; +0.0000511 WETH gross, net about −$0.32 (gas).
FlashArbExecutor deploy 0x054d7315…2cf924 Deployed to 0x9F56Db5E…cF891.
execute-flash (Balancer flash loan) 0x57946cee…faa947 Reverted at inclusion (state moved between snapshot and mined block). Atomic: gas only, no funds at risk.
execute-flash (Balancer flash loan) 0xac1277be…b34c0c Success. FlashArbExecuted(tier=2): borrow from Balancer Vault, cycle via TychoRouter, repay, sweep profit to owner. Contract left holding nothing.
execute-flash (Balancer flash loan, current TychoRouter) 0x34f4f533…d5cd3 Success. Settled through the current TychoRouter 0xdA892C…5736 (tycho-execution 0.302), the version this repo now targets.

The reverted flash tx demonstrates the safety model: the on-chain min-out guard reverts the whole atomic transaction when the opportunity has already been taken, so a failed race costs only gas. Landing a successful flash trade used wider slippage (--slippage-bps 300) plus --verify-top-n (an eth_call pre-check) to skip cycles that would revert.

This repo targets the current Tycho monorepo release (tycho-execution 0.302), so execution routes through the current TychoRouter. That router takes an automatic protocol fee on output (set by its FeeCalculator); this searcher does not stack an additional client fee on top (ClientFeeParams is left empty, which also avoids the router's per-call EIP-712 signature requirement for a non-zero client receiver). Flash execution uses the Balancer flash-loan path only; the UniV2 flash-swap path is disabled because the current router pulls input via transferFrom while the contract's uniswapV2Call pushes it. Re-enabling the UniV2 flash-swap path needs an approve(router) added to the contract callback plus a redeploy.

About

Cyclic arbitrage searcher built on Fynd's market data infrastructure

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages