CarryStrategy
RobinhoodCarryStrategy is a Uniswap v4 hook on Robinhood Chain. Brand new: its first pool went live today. Still in use: 2 trades in the last week, and 1 new pool this week.
- Contract name
- CarryStrategy
How this hook works
Trading taxA trading tax hook. It takes a cut of every trade, keeps rewards to claim and stops liquidity being added or removed directly.
Takes a cut of every trade
On top of the normal pool fee, it keeps a share of each trade. The fee can be changed. The fee builds up in the hook until it is collected.
The code that does this (beforeSwap):function beforeSwap(address sender, PoolKey calldata key, SwapParams calldata params, bytes calldata) external returns (bytes4, BeforeSwapDelta, uint24) { if (msg.sender != address(poolManager)) revert OnlyPoolManager(); _enter(); PoolId id = key.toId(); Pool storage p = pools[id]; if (!p.exists) revert UnknownPool(); if (!p.live) revert NotLive(); if (params.amountSpecified == 0 || params.amountSpecified == type(int256).min) revert BadParams(); (uint256 kb, uint256 ks, uint256 pb, uint256 ps) = _prepareSame(p); bool exactIn = params.amountSpecified < 0; uint256 spec = exactIn ? uint256(-params.amountSpecified) : uint256(params.amountSpecified); // input is currency0 when zeroForOne; the input is the coin on a sell bool sell = params.zeroForOne == p.coinIs0; (uint256 coinAmt, uint256 quoteAmt) = _fill(p.book.x, p.book.y, p.tX128, sell ? ks : kb, sell ? ps : pb, sell, exactIn, spec); if (sell) p.book.swap(int256(coinAmt), -int256(quoteAmt)); else p.book.swap(-int256(coinAmt), int256(quoteAmt)); Currency coinC = Currency.wrap(p.coin); Currency quoteC = Currency.wrap(p.quote); Currency inC = sell ? coinC : quoteC; Currency outC = sell ? quoteC : coinC; uint256 inAmt = sell ? coinAmt : quoteAmt; uint256 outAmt = sell ? quoteAmt : coinAmt; // claims only: the PoolManager need not hold the input token yet (the swapper pays after the hook runs) // …Rewards to claim
It keeps track of what people have earned, and they claim it themselves.
The code that does this (claim):function claim(PoolId id, uint256 lot) external lock returns (uint256 x, uint256 y) { Pool storage p = _live(id); _markLoss(p); (x, y) = BK.claim(p.book, lot, msg.sender); _moves(id, _pair(p, x, y, msg.sender, false)); emit Claimed(id, msg.sender, x, y); }Liquidity can’t be added or removed directly
Nobody can add or remove liquidity through Uniswap directly. Liquidity only moves through the hook’s own code.
Only approved callers create pools
New pools with this hook can only be created by approved callers, for example its own factory or launcher.
The code that does this (beforeInitialize):function beforeInitialize(address, PoolKey calldata, uint160) external view returns (bytes4) { if (msg.sender != address(poolManager)) revert OnlyPoolManager(); revert ExternalInit(); }No trading before the start
Trades are refused until trading has been opened.
The code that does this (beforeSwap):function beforeSwap(address sender, PoolKey calldata key, SwapParams calldata params, bytes calldata) external returns (bytes4, BeforeSwapDelta, uint24) { if (msg.sender != address(poolManager)) revert OnlyPoolManager(); _enter(); PoolId id = key.toId(); Pool storage p = pools[id]; if (!p.exists) revert UnknownPool(); if (!p.live) revert NotLive(); if (params.amountSpecified == 0 || params.amountSpecified == type(int256).min) revert BadParams(); (uint256 kb, uint256 ks, uint256 pb, uint256 ps) = _prepareSame(p); bool exactIn = params.amountSpecified < 0; uint256 spec = exactIn ? uint256(-params.amountSpecified) : uint256(params.amountSpecified); // input is currency0 when zeroForOne; the input is the coin on a sell bool sell = params.zeroForOne == p.coinIs0; (uint256 coinAmt, uint256 quoteAmt) = _fill(p.book.x, p.book.y, p.tX128, sell ? ks : kb, sell ? ps : pb, sell, exactIn, spec); if (sell) p.book.swap(int256(coinAmt), -int256(quoteAmt)); else p.book.swap(-int256(coinAmt), int256(quoteAmt)); Currency coinC = Currency.wrap(p.coin); Currency quoteC = Currency.wrap(p.quote); Currency inC = sell ? coinC : quoteC; Currency outC = sell ? quoteC : coinC; uint256 inAmt = sell ? coinAmt : quoteAmt; uint256 outAmt = sell ? quoteAmt : coinAmt; // claims only: the PoolManager need not hold the input token yet (the swapper pays after the hook runs) // …Anyone can trigger payouts
Anyone can send the collected fees on to where they go, so nobody has to wait on the hook developer.
The code that does this (sweep):function sweep(PoolId id) external lock { _live(id); poolManager.unlock(abi.encode(OP_SWEEP, id, address(0), uint16(0), new Move[](0))); }
Who controls it: The hook developer can change the fee and the trading limits. The hook developer can also change: leader, tip rule, depth rule, tail, carry. The hook developer can also call: propose admin, accept admin. The pool creator can change: creator. The code cannot be changed.
Based on the hook’s published code.What do these labels mean?
What it can do
Its code executes inside each trade in pools that use it.
It can take or add tokens during a swap. Fees, burns and custom curves work this way, and so do scams.
It runs before liquidity is removed, so it can delay or refuse LP exits.
It checks every deposit before it goes in.
It runs when a pool is created, often to lock in that pool’s settings.
Hook history
Across all its pools, the hook modify liquidity: $125.00, and handled a trade: $25.60.
- Modify liquidity 2 times, worth $125.00
Latest transactions
- 0x6493d48a…95469a block 113,069,789
- 0x9096328a…676c4c block 112,951,788
- Handled a trade 2 times, worth $25.60
Latest transactions
- 0x1d4f6edf…358c49 block 113,008,310
- 0x825154ac…d5d765 block 113,003,559
- Moved the tail 4 times
Latest transactions
- 0xf0479dbe…83ef98 block 113,032,171
- 0x9d221645…924631 block 113,022,013
- 0x1d4f6edf…358c49 block 113,008,310
- 0x533c9cb6…7ddaa4 block 112,951,804
- Tipped 4 times
Latest transactions
- 0xd1e14a4e…9ce84a block 113,042,057
- 0xb898cbed…1f174f block 113,041,919
- 0xa6d0499e…80899a block 113,036,465
- 0xd97e7dfb…eb6b8b block 113,024,542
- Burned tokens 3 times
Latest transactions
- 0xf0479dbe…83ef98 block 113,032,171 · 60.32 steakUSDG
- 0x9d221645…924631 block 113,022,013 · 15.08 steakUSDG
- 0x1d4f6edf…358c49 block 113,008,310 · 3.55 steakUSDG
- Took in a deposit 1 time
- Funded the jar 1 time
- Paid out rewards 1 time
- Created 1 time
Settings changes: set the tail (2 times), changed who controls the hook (1 time), proposed a new controlling wallet (1 time), changed the guardian wallet (1 time).
Counted from what the hook recorded on-chain across all its pools, for every action in its published code, plus token transfers in and out of it. Dollar values count the amounts paid in ETH, stablecoins, BNB and BTC, at today’s prices.