← back to PORTFOLIO · plain-text version
Network: Robinhood Chain, chainId 4663. Public RPC: https://rpc.mainnet.chain.robinhood.com.
| Contract | Address |
|---|---|
| LONGFOLIO (the coin, 18 decimals) | 0x9A64C06795b254C8aA70086E9FDC0FBE136F0110 |
| Zap / hook (buy & sell entry point) | 0x04D9d2cdacDf8E95484eC787E40479B109Bb6888 |
| L8NG basket token | 0xE607Ce5825517c0581fb22CB635578b28c2A62b2 |
| Uniswap V4 PoolManager | 0x8366a39CC670B4001A1121B8F6A443A643e40951 |
| Universal Router | 0x8876789976decbfcbbbe364623c63652db8c0904 |
| Permit2 | 0x000000000022D473030F116dDEE9F6B43aC78BA3 |
| V4 Quoter | 0x8dc178efb8111bb0973dd9d722ebeff267c98f94 |
PoolKey {
currency0: 0x0000000000000000000000000000000000000000 // native ETH
currency1: 0x9A64C06795b254C8aA70086E9FDC0FBE136F0110 // LONGFOLIO
fee: 0
tickSpacing: 1
hooks: 0x04D9d2cdacDf8E95484eC787E40479B109Bb6888
}
poolId = 0xd2adda941c977b675e4a60bba17e84e45ccd110913e1ec206a46da2c1895314d
The pool holds no liquidity of its own. The hook does the whole trade inside beforeSwap: ETH → the 8 basket tokens → mints L8NG → swaps L8NG for LONGFOLIO on the Long pool, and hands the coin back through the PoolManager. Consequences for integrators:
slot0 and getLiquidity are meaningless (price fixed at 1.0, liquidity 0). Use the Quoter for price.Swap event for this pool always shows amount0 = amount1 = 0. Use the zap events for trades and volume (below).eth_estimateGas or the Quoter's gasEstimate × 1.2. A 1M gas limit reverts.V4Quoter.quoteExactInputSingle((PoolKey, bool zeroForOne, uint128 exactAmount, bytes hookData)) → (uint256 amountOut, uint256 gasEstimate). Selector 0xaa9d21cb. Buy: zeroForOne = true, exactAmount = wei of ETH, hookData = 0x. Sell: zeroForOne = false, exactAmount = LONGFOLIO wei. Call it with eth_call (it is not declared view, but it returns normally).
execute(bytes commands, bytes[] inputs, uint256 deadline), selector 0x3593564c, send the ETH as value)commands = 0x10 // V4_SWAP
actions = [0x06, 0x0c, 0x0e] // SWAP_EXACT_IN_SINGLE, SETTLE_ALL, TAKE
params[0] (SWAP_EXACT_IN_SINGLE) = abi.encode((PoolKey, true, uint128 amountIn, uint128 minOut, bytes ""))
params[1] (SETTLE_ALL) = abi.encode(address(0), uint256 amountIn)
params[2] (TAKE) = abi.encode(LONGFOLIO, address recipient, uint256 0) // 0 = take the full credit
inputs[0] = abi.encode(actions, params)
viem example:
const KEY = { currency0: "0x0000000000000000000000000000000000000000", currency1: "0x9A64C06795b254C8aA70086E9FDC0FBE136F0110", fee: 0, tickSpacing: 1, hooks: "0x04D9d2cdacDf8E95484eC787E40479B109Bb6888" };
const KEY_T = { type: "tuple", components: [{name:"currency0",type:"address"},{name:"currency1",type:"address"},{name:"fee",type:"uint24"},{name:"tickSpacing",type:"int24"},{name:"hooks",type:"address"}] };
const swap = encodeAbiParameters([{ type: "tuple", components: [KEY_T, {type:"bool"},{type:"uint128"},{type:"uint128"},{type:"bytes"}] }], [[KEY, true, amountIn, minOut, "0x"]]);
const settle = encodeAbiParameters([{type:"address"},{type:"uint256"}], ["0x0000000000000000000000000000000000000000", amountIn]);
const take = encodeAbiParameters([{type:"address"},{type:"address"},{type:"uint256"}], [KEY.currency1, recipient, 0n]);
const input = encodeAbiParameters([{type:"bytes"},{type:"bytes[]"}], ["0x060c0e", [swap, settle, take]]);
await router.write.execute(["0x10", [input], deadline], { value: amountIn, gas: 6_000_000n });
Direct PoolManager integration: unlock → swap(key, {zeroForOne: true, amountSpecified: -int256(amountIn), sqrtPriceLimitX96: 4295128740}, "") → settle the ETH, take the coin. Sell: zeroForOne = false, limit 1461446703485210103287273052203988822378723970341.
zeroForOne = false, SETTLE_ALL(LONGFOLIO, amountIn) and TAKE(address(0), recipient, 0). Needs LONGFOLIO.approve(Permit2, max) and Permit2.approve(LONGFOLIO, UniversalRouter, amount, expiration) (selector 0x299ec9ee).sell(uint256 coinIn, uint256 minEthOut, uint256 deadline) (selector 0xd3c9727c) after LONGFOLIO.approve(zap, amount). ETH is sent to the caller.buy(uint256 minCoinOut, uint256 deadline) payable, selector 0xd6febde8, on 0x04D9d2cdacDf8E95484eC787E40479B109Bb6888. Send ETH as value; the coin goes to msg.sender. Gas ≈ 5M.
1 L8NG in ETH = sum of spotSplit() (selector 0x80d84b0d, uint256[] wei per 1e18 L8NG) on the zap; LONGFOLIO priced in L8NG lives on the Long pool below.0x04D9…6888:| Event | topic0 |
|---|---|
HookBought(address indexed router, uint256 ethIn, uint256 basketMinted, uint256 coinOut) — buys through the PoolManager / any router | 0x18da56f4ab10a2ade66d651ee18224cfa82d3581722faa4e401270e41ac3a66f |
HookSold(address indexed router, uint256 coinIn, uint256 basketOut, uint256 ethOut) | 0xb315275ffd13ef67d85701c2113ee48e84997f7f67c8f91ab5d38435c2c731de |
Bought(address indexed user, uint256 ethIn, uint256 basketMinted, uint256 coinOut, uint256[] refunded) — zap.buy | 0x41c6893c9c9b0ea553f4bc3bd6586a0adfe88ac8a5301b1d7cef460799197f6d |
Sold(address indexed user, uint256 coinIn, uint256 basketOut, uint256 ethOut) — zap.sell | 0xe029f26dbcf8c42dd2f352c10214a7fc26773dc62482c6241334a0402ac09a80 |
Swap events with real amounts, price in L8NG: PoolKey(LONGFOLIO, L8NG, 0x800000, 8, 0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544) (currencies sorted by address). LP fee 2.1%.| Selector | Meaning | What to do |
|---|---|---|
0x90bfb865 WrappedError(...) | the hook reverted; the inner selector is inside | decode the inner reason |
0x590f58a9 PartialFill(member, hop, consumed, wanted) | one basket leg's pool could not absorb the leg | retry with a smaller amount |
0x2746152a Slippage(got, min) | minOut not met | re-quote |
0x203d82d8 Expired() | deadline passed | new deadline |
| out of gas at ~1M | gas limit too low | 6M gas limit |
Notes: buys through a router may return small amounts of basket member tokens to tx.origin (leftovers above 0.5% of a leg are refunded to the buyer). Every trade pays the 2.1% pool fee plus the basket routes (≈1.8%); there is no anti-snipe fee anymore.
Questions: @portf0110 on X