An automated currency price-matching bot. Quarry spots temporary price differences across crypto exchanges and balances them instantly.
If a store across town sells an item for $10 and another buys it for $12, a quick courier can make a $2 profit while helping keep prices fair. Quarry monitors decentralized exchanges around the clock, spotting momentary price differences and executing instant trades with zero upfront capital using flash loans.
Quarry operates as a hybrid MEV arbitrage engine. A TypeScript scanner watches Ethereum's public mempool for swaps about to land on a Uniswap-V2-shaped DEX. For each candidate, it computes the post-trade price impact, runs a closed-form optimal-input solver against the reserves, and packs a 220-byte calldata payload whenever round-trip profit covers fees and gas. The executor is a custom Yul contract (492 bytes of runtime bytecode) that performs the full two-hop arbitrage and reverts atomically if realized profit falls short.
Scope: Quarry targets cross-DEX arbitrage (closing price gaps to improve market price efficiency). Predatory strategies such as sandwiches or JIT attacks against retail traders are strictly out of scope. See CONTRIBUTING.md.
The executor keeps a trade only when its own balance grows by at least minProfit. Otherwise the transaction reverts and neither swap takes effect.
The scanner decodes a pending Uniswap V2 swap, reads both pools through Multicall3, and sizes the trade with a closed-form solver. A signed EIP-1559 transaction carries 220 bytes of packed calldata to the Yul executor, which swaps on the victim pool with to=Pool2 and then on the counter pool with to=this. Editable HTML source.
The executor is built in monolithic Yul bytecode without heavy framework overhead. Data is read directly as a tightly packed byte string. Pool 1's output flows directly to pool 2 (a classic decentralized exchange optimization where tokens transfer straight between liquidity pools, skipping intermediate transfers to save transaction fees). A balance snapshot at entry and exit guards the trade: if the price difference disappears before the transaction completes, the entire transaction cancels automatically with zero loss of funds.
Quarry/
βββ contracts/ # Foundry project: smart contract executor + tests
β βββ src/Executor.yul # 492-byte runtime, two-hop executor
β βββ test/Executor.t.sol # Tests, mock pools, safety assertions
β βββ test/ExecutorFork.t.sol # Tests against real network state
β βββ foundry.toml
βββ bot/ # TypeScript scanner (Bun runtime)
β βββ src/amm.ts # Constant-product pricing math + solver
β βββ src/decode.ts # Transaction decoder + exchange registry
β βββ src/pairs.ts # Address derivation utilities
β βββ src/reserves.ts # Multi-pool reserve fetcher
β βββ src/score.ts # Opportunity scoring engine
β βββ src/gas.ts # Gas price estimator
β βββ src/bundle.ts # Compact payload builder
β βββ src/sign.ts # Transaction signing
β βββ src/scanner.ts # Live transaction stream scanner
β βββ scripts/demo.ts # End-to-end demo runner
β βββ test/ # 60 automated tests, 2,121 assertions
βββ JOURNAL.md # Architecture and incident log
βββ CONTRIBUTING.md # Scope and contribution guidelines
βββ LICENSE
The two subtrees are intentionally independent. They communicate only through deployed contract addresses and standard binary interfaces. See JOURNAL.md for details.
# Toolchain (macOS)
brew install foundry oven-sh/bun/bun
# Clone + install deps
git clone https://github.com/Builder106/quarry.git
cd quarry
cp .env.example .env # fill in MAINNET_RPC_URL for fork tests
# On-chain side
cd contracts
forge install
forge test # 7 mock tests, fork test skips without RPC
MAINNET_RPC_URL=https://... forge test # full suite incl. real-pool fork test
# Off-chain side
cd ../bot
bun install
bun run typecheck
bun test # 60 tests, 2,121 assertionsThe full pipeline runs against a local anvil fork β including the Aave V3 flashloan that funds the back-run. The bot holds zero inventory; Aave fronts the WETH and gets repaid atomically + 5 bp premium inside the same transaction.
To reproduce locally:
# Terminal 1 β fork mainnet at HEAD
anvil --fork-url https://ethereum-rpc.publicnode.com
# Terminal 2 β run the pipeline
cd bot
bun run demoFull trace β click to expand the verbatim output of bun run demo
[demo] anvil reachable at http://localhost:8545
[demo] bot account: 0xf39Fβ¦2266
βββ DEPLOY βββ
[demo] executor deployed at 0xabab79ac4a0ea727dd012cb1b843fe84baed64b6
[demo] deploy gas used: 181484
βββ SCORE (pre-victim) βββ
[demo] UniV2 0xB4e1β¦C9Dc USDC=9141845.119648 USDC WETH=4454.860040 WETH
[demo] Sushi 0x397Fβ¦ACa0 USDC=127232.684254 USDC WETH=61.999499 WETH
[demo] hypothetical victim: 0x0000β¦bEEF sells 1000000.000000 USDC for WETH on UniV2
[demo] scored uniswap-v2 β sushiswap
[demo] base: WETH (0xC02aβ¦6Cc2)
[demo] intermediate: USDC (0xA0b8β¦eB48)
[demo] amountIn: 5.301040 WETH
[demo] intermediateOut: 13326.704675 USDC
[demo] expectedOut: 5.862323 WETH
[demo] predicted profit: 0.561283 WETH
[demo] gas estimate: 163085461950000 wei
βββ VICTIM EXECUTION βββ
[demo] dealt 1000000.000000 USDC to victim
[demo] victim swap mined: 0x55c951d0984ccfc4c0dc8dd187dba8e30d46ab41ce4dd8cf7cbbf645cd6b1c36
[demo] UniV2 0xB4e1β¦C9Dc USDC=10141845.119648 USDC WETH=4016.792843 WETH
[demo] Sushi 0x397Fβ¦ACa0 USDC=127232.684254 USDC WETH=61.999499 WETH
βββ FLASHLOAN BUNDLE βββ
[demo] borrowing 5.301040 WETH from Aave V3 (0x8787β¦A4E2)
[demo] Aave premium (5 bp on WETH): 0.002650 WETH
[demo] expected net (profit β premium): 0.558632 WETH
[demo] target: 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2
[demo] calldata: 0x42b0b77c000000000000β¦00000000 (420 bytes)
[demo] signed tx: 0x02f9021301821920843bβ¦5eb979a7
[demo] flashloan tx mined: 0x24a799fedb42d8c23dfb42a987d8cece89fffe76bc96d5b21cdb077332edc4bd
[demo] tx gas used: 266694
βββ VERIFY βββ
[demo] executor's final WETH balance: 0.558046 WETH
[demo] gross predicted profit: 0.561283 WETH
[demo] aave premium: 0.002650 WETH
[demo] net predicted profit: 0.558632 WETH
[demo] net realized profit: 0.558046 WETH
[demo] prediction accuracy: 99.89% of expected
[demo] β end-to-end flashloan-funded pipeline complete.The 0.11% drift between net predicted and net realized is exactly the 2 bp safety margin baked into the calldata builder for Uniswap V2's K-invariant integer-arithmetic check β see JOURNAL.md for why.
A second script reads the current WETH/USDC reserves on Uniswap V2 + Sushiswap (no synthetic victim), runs the bot's standing-arb math in both possible round-trip directions, and either executes via Aave V3 flashloan when a real profitable gap exists, or prints a diagnostic gap analysis showing each direction's predicted loss-to-fees.
# Terminal 1 β anvil at HEAD (no archival needed)
anvil --fork-url https://ethereum-rpc.publicnode.com
# Terminal 1, alternate β pin to a known-arb block (needs archival RPC)
anvil --fork-url $ALCHEMY_URL --fork-block-number 15990000
# Terminal 2
cd bot && bun run replayAt any random recent block, the typical cross-DEX gap on WETH/USDC is well below the combined ~0.6% round-trip fee β competing MEV bots close real gaps within the same block they form. The script's diagnostic mode shows that:
βββ RESERVE SNAPSHOT βββ
[replay] UniV2 0xB4e16d⦠USDC=9152516.072170 USDC WETH=4449.682244 WETH
[replay] Sushi 0x397FF1β¦ USDC=127338.484262 USDC WETH=61.948146 WETH
[replay] cross-DEX gap: 0.060% (round-trip fee floor is ~0.60%)
β¦
βββ DIAGNOSIS βββ
[replay] no profitable arb at block 25189150.
[replay] this is normal at any random recent block β competing
[replay] MEV bots close cross-DEX gaps within the same block they
[replay] form. To find a real historical opportunity, pin anvil
[replay] to a block of high volatility (large liquidations, mempool
[replay] congestion, etc.) and re-run with archival RPC access.
Pinning FORK_BLOCK to a moment of high volatility (liquidation cascades, large mempool trades that landed without a back-runner) converts the diagnostic into a real historical-arb replay.
| Surface | Gate | Current |
|---|---|---|
| Two-hop arb total gas (real pools) | β€ 130,000 on forked mainnet | 110,780 |
| Yul runtime bytecode size | β€ 512 B | 492 B |
| Mocks-test gas regression ceiling | β€ 50,000 | 48,976 |
| Scanner p99 tx-to-decision | β€ 20 ms on 1-hour sample | β (not yet benched) |
| Scanner hot path | 0 heap allocations per pending-tx event | β |
Forked-mainnet gas measurement uses real Uniswap V2 + Sushiswap WETH/USDC pairs at HEAD. The Yul executor's own opcodes contribute ~6k of that β the remainder is the unavoidable cost of the two pool swap() calls themselves. A vanilla Solidity equivalent of this contract typically lands at 150β250k total under the same conditions.
Snapshots checked into contracts/.gas-snapshot. PRs that regress these need justification β see CONTRIBUTING.md.
- Yul executor: chained two-hop swap on Uniswap-V2-shaped pools with balance-snapshot revert guard. Real-pool fork test green at 110k gas.
- Scanner: WebSocket pending-tx β router filter β calldata decode β multicall reserves β back-run scoring (apply victim β solve optimal input) β 220-byte calldata.
- Gas gate: refuses to surface opportunities where profit (in WETH terms) doesn't beat the bundle's gas cost at current gas prices.
- EIP-1559 signing + Flashbots-shape
eth_sendBundleenvelope. - End-to-end demo runs against forked mainnet, asserts realized profit matches prediction within 1%.
Known V0 limitations (documented in JOURNAL.md)
- Scanner only scores the first hop of a victim's
pathβ multi-hop paths fan out the search surface but aren't yet expanded. - Only
exactInForTokensvictim swaps trigger scoring; ETH-side variants (swapExactETHForTokens, etc.) decode but don't yet plumbtx.valuethrough. - Gas gate only fires for WETH-base trades; non-WETH-base profits would need a WETH/baseToken conversion via a third reserve fetch.
- No flashloan integration β the demo simulates the flashloan via
setStorageAt. Production deployment would add an Aave V3 flashloan tx in bundle position 0. - No actual Flashbots relay submission. The bundle is shaped correctly but the demo submits to a local anvil, not a real relay.
MIT β see LICENSE.
