Documentation

How Kerf works

Short, and precise about what is live, what is a preview and what is not connected. Every number the product shows traces back to a chain read at a stated block.

01Overview

Kerf looks for price differences in the same verified stock token across Uniswap pools on Robinhood Chain. It assembles closed loops that begin and end in one settlement asset (USDG or WETH), prices them with the on-chain quoter, lists every cost on its own line, and replays the exact executor call from your address. When a verified executor is deployed you can run an eligible loop atomically from your own wallet.

There is a token, $KERF, whose address is published on this site once it exists — and the app does not use it for anything. Most of the time no loop is eligible. An efficiently arbitraged market is the normal state, and the scanner tells you so.

02Network

FactValueWhere it comes from
ChainRobinhood Chain · 4663Operator docs + live eth_chainId
TypeArbitrum Orbit L2, Ethereum blobs for dataOperator docs
Gas tokenETHOperator docs
Explorerrobinhoodchain.blockscout.comOperator docs
Public RPChttps://rpc.mainnet.chain.robinhood.comRate-limited, not for production — put a provider URL in KERF_RPC_URL (server-side)
Testnet46630 — unusedNo Uniswap deployment is listed there, so nothing can be verified

Blocks land roughly every 0.1 s. Cross-chain loops are out of scope: a cycle spread across two chains can never be atomic.

03Assets and pools

Assets. The asset list is the issuer’s stock-token registry (https://api.robinhood.com/rhj/assets). A ticker proves nothing — look-alike tokens exist — so each address must also be an ERC-1967 beacon proxy of the issuer beacon 0xe10b6f6B275de231345c20D14Ab812db62151b00 with matching symbol() and decimals(). Settlement assets are USDG 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168 (6 decimals) and WETH 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73 (18 decimals).

Pools. For every stock token × {USDG, WETH} × fee tier (0.01, 0.05, 0.30, 1 %) we call factory.getPool, plus factory.getPair for V2 and the WETH/USDG connectors. Asking the canonical factory is the membership proof. Stock/stock pools are found with a bounded PoolCreated scan and re-checked with getPool at run time.

Depth probes. A V3 position one tick wide can report huge liquidity and fill almost nothing. Every pool above the dust floor (25 USDG of +1 % depth) is sent a real quote of up to 1,000 USDG that must fill within 3 % impact beyond its fee. Pools that fail are marked hollow and excluded from spreads and routing.

Uniswap v4. v4 pools between verified assets are listed from a PoolManager census as an unsupported venue. They are never priced or routed: hooks can change fees and pricing, and the executor cannot settle v4 swaps.

04Prices and quotes

  • All pool state in one comparison is read in a single multicall pinned to one block; that block number travels with the data to the screen.
  • Spot prices (V3 from sqrtPriceX96, V2 from reserves) are indicative: before impact, not an exchange price, not an oracle.
  • The raw spread — dearest minus cheapest verified pool of an asset — is a signal and never a result.
  • Candidate loops of 2–4 distinct pools are ranked by spot edge; the best 48 are quoted hop by hop with QuoterV2 (0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7), each quote an isolated, gas-capped eth_call, at 5, 15, 40, 100 and 250 % of the loop’s shallowest depth. V2 hops use constant-product maths on same-block reserves.
  • Quotes expire after 20 s. The scanner may show a scan up to 90 s old while it refreshes — every row shows its age — and the route panel always re-quotes at the newest block.

05Cost accounting

LineHow it is obtained
Raw price spreadProduct of spot rates after pool fees, minus 1. Used only for ranking.
Quoted route outputQuoterV2 or V2 formula, hop by hop. Pool fees and impact are already inside it.
Trading feesInside the quote; never subtracted a second time.
Flash-liquidity feeNone on top: the flash swap repays the first pool in the settlement asset, and that pool’s swap fee is the whole borrowing cost.
Protocol fee0 % by default, and only of a positive result. Fixed per deployment, capped at 10 %; the live value is read from the contract.
Gaseth_estimateGas of the real call in the route panel (a measured model × 1.25 in the scan), times the current gas price.
Gas in the settlement assetOnly via a credible same-block rate: the deepest depth-verified WETH/USDG pool (≥ 10,000 USDG deep), vetoed if Chainlink ETH/USD ÷ USDG/USD disagrees by more than 2 %. Otherwise gas stays in ETH and the net is flagged incomplete.
Estimated result after costsQuoted result − protocol fee − gas, when gas could be converted.
Required minimum resultmax(floor, estimate × accepted share), enforced on-chain after the protocol fee. The floor defaults to the estimated gas.

On the backend every amount is an integer in base units with the token’s own decimals. Amounts you receive round down; costs round up.

06Simulation

“Simulate exact call” runs execute(hops, amountIn, minProfit, deadline) in an eth_call at the latest block, from your address (a placeholder before you connect), and estimates its gas. The response echoes the exact calldata. A simulation is bound to the route, amount, minimum rule, deadline, wallet, chain and contract: change any of them, let it age past 30 s, or get within 20 s of its deadline, and it no longer counts. Deadlines (30–600 s) are measured in chain time.

While no executor is deployed, the same compiled bytecode is injected at a scratch address through an eth_call state override and run against live state — labelled preview. It shows what the contract would do; there is nothing to sign.

A passing simulation is not a guarantee. State changes about ten times a second, other traders watch the same pools, and a reverted transaction still costs gas.

07Executor

Mechanics. The executor calls swap on the first pool; Uniswap sends the output first and then calls back (uniswapV3SwapCallback / uniswapV2Call). Inside the callback the other hops run exact-input on the amounts actually received, the first pool is repaid, and profit is the rise in the contract’s settlement balance over the whole call. Your minimum is checked after the protocol fee and the rest is sent to you — in one transaction or not at all. You supply no tokens and grant no allowance.

  • Every hop must be the pool the immutable V2/V3 factory returns for its tokens and fee: no arbitrary call targets, no caller-supplied calldata.
  • Callbacks are accepted only during an execution, only from the single pool expected next, and only once; the flash payload is hash-pinned.
  • Balances already sitting in the contract can neither subsidise a loop nor leak: payout is the measured increase, and no increase means revert.
  • Received amounts must equal what the pool reported (rejecting fee-on-transfer and rebasing tokens); partial fills revert; tokens are allow-listed; 2–4 hops; deadline; immutable fee cap.

The owner can allow or block tokens, change the fee recipient, pause new executions and sweep non-fee balances. The owner cannot change the fee or the factories, redirect a caller’s profit, take user tokens, or upgrade the contract (it is not a proxy).

Covered by unit tests on real Uniswap V2/V3 bytecode and mainnet-fork tests on real stock-token pools. Not independently audited.

08Transactions and history

Before your wallet opens, the call is re-quoted and simulated again, on the server and in your browser; the wallet receives exactly those bytes. States move only on real events: re-simulated → awaiting wallet → submitted → pending → confirmed or reverted (plus rejected, replaced and cancelled). Success exists only after a receipt with status success; proceeds are decoded from its CycleExecuted event.

History rows come from CycleExecuted events and receipts. Each carries a confirmation state from the node’s block tags — on L2, batch posted to L1 (safe), or finalized on L1 — and the last 256 blocks are re-scanned on every pass so a reorganised execution disappears. Proceeds and gas are shown apart unless both are in ETH. Transactions this browser submitted are tracked by receipt. CSV export writes exact units.

09Integrations

IntegrationStatusSource / reason
Uniswap V2 factorysupported0x8bcEaA40B9AcdfAedF85AdF4FF01F5Ad6517937f · Uniswap deployments registry
Uniswap V3 factory · QuoterV2supported0x1f7d7550B1b028f7571E69A784071F0205FD2EfA · 0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7 · factory() and WETH9() cross-checked
Multicall3used for reads0xcA11bde05977b3631167028862bE2a173976CA11
Stock token registry + beaconsupportedhttps://api.robinhood.com/rhj/assets · 0xe10b6f6B275de231345c20D14Ab812db62151b00
Chainlink ETH/USD, USDG/USDcross-check only0x78F3556b67E17Df817D51Ef5a990cDaF09E8d3A9 · 0x61B7e5650328764B076A108EFF5fa7282a1B9aD2
Chainlink sequencer-uptime feednot availableRecommended by the chain docs; none is listed for chain 4663.
Uniswap v4 PoolManagerlisted, not routed0x8366a39CC670B4001A1121B8F6A443A643e40951 · hooks can change pricing; no v4 settlement adapter
Morpho Blue flash loansavailable, unusedUniswap flash swaps already fund every supported loop at no extra fee; a second funding path would add attack surface and change nothing.
Order-book / perps venues, aggregatorsnot integratedNo verified on-chain quote interface for spot loops; nothing is inferred from them.

The typed registry lives in src/config/registry.ts; the backend should re-check it against its sources and the live chain on start-up.

10Token

$KERF is the Kerf token. Its contract address is published in exactly two places: the token section of the home page and the pill in the header. Anything else claiming to be $KERF is not.

The app does not use the token. Scanning, quoting, simulation and execution never read a $KERF balance: no staking, no treasury, no yield, no fee discount, no reward, no governance, no promised value. Once live, the site shows only what the chain reports at a stated block — the contract facts and, if a canonical V2/V3 pool against USDG or WETH holds liquidity in range, its spot price and +1 % depth. If there is no such pool, it says so.

11Limitations

  • A web interface is slow next to a co-located bot. Expect gaps to close before inclusion; reverts cost gas.
  • The +1 % depth figure is an indicator; probes only verify up to 1,000 USDG.
  • Sizes come from a five-step ladder, not a continuous optimiser.
  • The public RPC throttles and is not archival; the last good read stays on screen, marked stale, next to the real error.
  • Stock tokens can be paused, block-listed or upgraded by their issuer; a loop touching one then reverts.

12Developer interface

struct Hop { address pool; address tokenIn; address tokenOut; uint24 fee; uint8 kind; } // kind 0 = V2, 1 = V3

function execute(Hop[] calldata hops, uint256 amountIn, uint256 minProfit, uint256 deadline)
  external returns (uint256 userProfit, uint256 protocolFee);

event CycleExecuted(address indexed caller, address indexed settlementToken, uint256 amountIn,
  uint256 grossProfit, uint256 userProfit, uint256 protocolFee, address[] pools);
EndpointReturns
GET /api/marketsPools, prices, depth, probes and gas reference at one block.
GET /api/pools/v4?page=&includeExtreme=Uniswap v4 pools between verified assets (listed, unsupported), paginated.
GET /api/routes?settlement=USDG|WETH&maxHops=2..4&token=0x…Quoted loops with accounting, rejection reasons and excluded pools.
POST /api/quoteFresh quote for one route; with simulate: true, the exact-call simulation and its calldata.
GET /api/activity?caller=0x…&page=1&limit=25Receipt-derived history with confirmation state.
GET /api/statusNetwork, finality tags, adapters, freshness, registry provenance, executor checks.
GET /api/token$KERF: “soon”, or the address with name, symbol, decimals, supply and market at one block.