Robinhood Chain · chain 4663
Contracts
Five contracts. Two of them, the lens and the router, are all most integrations ever touch.
Addresses
PackRegistry
Register and look up packs
PackHook
The v4 hook behind every pack pool
PackLens
Reads, including NAV
PackRouter
Buy and sell packs
PoolManager
Uniswap v4
The same set, machine readable, is at /.well-known/lnchr.json. ABIs are served at https://lnchr.io/abi/PackLens.json and the same path for each of the five.
PackRegistry
Registers packs and holds the list of stocks a pack can be built from, each with a curated route. register(stocks, prices, deadline, signature) deploys the vault at a CREATE2 address derived from the ordered list, so the same list can never exist twice and the address is knowable in advance. isPack(address) is the one call an integrator needs.
register(address[] stocks, uint256[] pricesUsd, uint256 deadline, bytes signature) returns (address)
isPack(address) view returns (bool)
predict(address[] stocks) view returns (address)
tickerOf(address[] stocks) view returns (string)
packCount() view returns (uint256)
allPacks(uint256) view returns (address)
routeOf(address stock) view returns (Route)PackVault
The pack itself, one per registered combination, deployed by the registry. A plain ERC-20 with an immutable ordered stock list and fixed quantities per unit. mint and redeem are open to anyone: redeem hands back the underlying stocks pro rata on the vault's actual balances, which is also how dividends and corporate actions reach holders. No owner, no pause, no proxy.
stocks() view returns (address[])
unitQty() view returns (uint256[])
composition() view returns (uint256[])
holdings() view returns (uint256[])
required(uint256 units) view returns (uint256[])
mint(uint256 units, address to) returns (uint256)
redeem(uint256 units, address to) returns (uint256[])PackHook
The Uniswap v4 hook every pack pool runs on. beforeSwap replaces the swap: a buy takes the quote asset in, buys each stock on its own curated route, mints the pack and delivers it; a sell runs backwards. The pools hold no reserves, reject liquidity and need no arbitrage, because every trade moves the underlying. Two pools per pack, against WETH and USDG.
poolKey(address pack, address quote) view returns (PoolKey)
packOfPool(PoolId) view returns (Pack)PackLens
The read surface. One call returns everything about a pack, including NAV, so nothing has to reach into registry or vault internals.
packInfo(address pack) view returns (PackView)
packs(uint256 offset, uint256 limit) view returns (PackView[])
navUsdg(address pack) view returns (uint256)
stocks() view returns (StockView[])
exists(address[] stocks) view returns (bool, address, string)
poolKeyFor(address pack, address quote) view returns (PoolKey)PackRouter
Buying and selling packs without driving a v4 unlock yourself. Each call is one transaction and returns the amount out, so simulating it is also how you quote it.
buyWithEth(address pack, uint256 minOut) payable returns (uint256)
buyWithUsdg(address pack, uint256 amountIn, uint256 minOut) returns (uint256)
sellForEth(address pack, uint256 amountIn, uint256 minOut) returns (uint256)
sellForUsdg(address pack, uint256 amountIn, uint256 minOut) returns (uint256)Verifying a pack yourself
Everything a pack claims is checkable on chain without trusting this site: the vault's stock list and quantities are immutable, its holdings are ERC-20 balances you can read directly, and redeem pays them out pro rata to anyone who asks.