Skip to content

jumpboxtech/rhcswap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RHCSwap

Swap on Robinhood Chain without the SDK reverts.

Robinhood Chain ships a modified Uniswap UniversalRouter — its v4 swap struct carries an extra minHopPriceX36 field — so calldata built by the standard Uniswap SDK reverts. (There are also look-alike router addresses floating around the chain; only one is real.)

RHCSwap sidesteps the router entirely and talks to the Uniswap v4 PoolManager directly: unlock → swap → settle → take. That path is plain, unmodified v4 — the quirk only lives in the router layer. ~140 lines, zero dependencies, no owner, no state.

Proven on live Robinhood Chain: 1 NVDA → $201.98 USDG, ~167k gas, nothing stranded.


How it works

A v4 swap has to happen inside the PoolManager's unlock callback, and every currency balance-delta must net to zero before unlock returns — otherwise it reverts. RHCSwap does exactly that:

sequenceDiagram
    autonumber
    participant U as Your contract
    participant R as RHCSwap
    participant PM as v4 PoolManager
    U->>R: swap(key, zeroForOne, amountIn, minOut, to)
    R->>R: pull amountIn of tokenIn (transferFrom)
    R->>PM: unlock(data)
    PM->>R: unlockCallback(data)
    R->>PM: swap(key, {exactInput, priceLimit})
    PM-->>R: BalanceDelta (−in, +out)
    R->>PM: sync(tokenIn) · transfer(tokenIn) · settle()
    R->>PM: take(tokenOut, to, amountOut)
    Note over R,PM: deltas net to 0 → unlock returns
    R-->>U: amountOut
Loading

Install

forge install jumpboxtech/rhcswap

Use

Deploy RHCSwap (or reuse a deployment), approve it for your input token, and call swap:

import {RHCSwap, PoolKey, Currency} from "rhcswap/RHCSwap.sol";

// NVDA / USDG 0.3% pool. currency0 < currency1 by address:
// USDG 0x5fc5… < NVDA 0xd060…  → USDG is currency0.
PoolKey memory key = PoolKey({
    currency0: Currency.wrap(USDG),
    currency1: Currency.wrap(NVDA),
    fee: 3000,
    tickSpacing: 60,
    hooks: address(0)
});

IERC20(NVDA).approve(address(rhcSwap), amountIn);

// selling NVDA (currency1) for USDG (currency0) → zeroForOne = false
uint256 usdgOut = rhcSwap.swap(key, /*zeroForOne*/ false, amountIn, minUsdgOut, msg.sender);

Finding a pool's PoolKey

v4 doesn't have per-pair pool addresses — a pool is identified by its PoolKey. Get fee / tickSpacing / hooks for a pair from the pool's Initialize event on the PoolManager (topics carry currency0 / currency1; the data carries the rest). Then confirm liquidity / quote the output with the Quoter before you route real size — many RHC pools are thin or high-fee placeholders.


Robinhood Chain v4 addresses (chain id 4663)

Contract Address
PoolManager 0x8366a39CC670B4001A1121B8F6A443A643e40951
StateView 0xf3334192d15450cdd385c8b70e03f9a6bd9e673b
Quoter 0x8dc178efb8111bb0973dd9d722ebeff267c98f94

RPC: https://rpc.mainnet.chain.robinhood.com · Explorer: robinhoodchain.blockscout.com


Gotchas (things that cost me time)

  • amountSpecified is negative for exact-input.
  • sqrtPriceLimitX96zeroForOne ? MIN_SQRT + 1 : MAX_SQRT - 1. This gives no price protection — always pass a real minAmountOut; it's your only slippage guard.
  • Settle pattern is sync(currency) → transfer(currency, poolManager) → settle(). There is no settle(currency) in v4 — only the no-arg settle(), which settles the last-synced currency.
  • BalanceDelta packs amount0 in the high 128 bits and amount1 in the low 128 bits of an int256. Output leg is amount1 when zeroForOne, else amount0.
  • This assumes the pool's hooks == address(0). A hooked pool can mint/take extra deltas and break the settle/take netting — check the PoolKey first.

Scope & limits

Exact-input, single-hop, hookless pools — deliberately minimal. No multi-hop, no exact-output, no native ETH. It's a starting point; fork it. Unaudited — read it before you route funds through it.

Test

forge test --fork-url rhc -vv

Forks live Robinhood Chain and swaps a real NVDA holder's token → USDG through the real pool.

License

MIT © jumpbox — jumpbox.tech · @jumpbox_tech

About

Swap on Robinhood Chain without the SDK reverts — a zero-dependency Solidity helper that hits the Uniswap v4 PoolManager directly.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors