Home Swap Pools Docs
RehypDocsv0.1
Uniswap v4 · $REHYP · Technical Specification

Rehyp Docs

Long-form articles for the Rehyp Hook — a single Uniswap v4 contract that is the $REHYP ERC-20, runs three pools (WETH, USDC, GHO) with hook-owned inventory, and routes idle asset reserves into Aave v3 so yield can buy back and burn $REHYP.

Article Library

Browse the specification by section.

10 Sections
Overview

Executive Summary

One contract that is both the $REHYP token and a Uniswap v4 hook. Hook-owned inventory, three asset pools, Aave-fed buybacks.

5 minDraft
Overview

Background & Primitives

Uniswap v4 custom accounting, the prepaying unlock router pattern, and Aave v3 aTokens — the building blocks the hook composes.

6 minDraft
Architecture

Architecture Overview

One hook contract, three asset pools (WETH, USDC, GHO), per-asset Aave v3 vaults. Component map and accounting flow.

8 minDraft
Architecture

Hook Logic in Detail

How beforeSwap takes input, settles output, withdraws from Aave on demand, and re-deposits the raw buffer surplus.

12 minDraft
Architecture

Yield Harvest & Burn

How accrued aToken interest is converted into a REHYP buy along the curve and then permanently burned from the supply.

6 minDraft
Build

Pricing Model

Virtual constant-product: (xReserve + xVirtual) · yReserve = k. How the initial price is seeded without LP liquidity.

6 minDraft
Build

Solidity Surface

The actual entry points: quoteBuy, quoteSell, harvestYield, rebalanceRaw, poolView.

8 minDraft
Token

The $REHYP Token

50M supply, no inflation, hook-owned inventory across three pools, deflationary via Aave yield buybacks.

5 minDraft
Operations

Risk Analysis

Aave v3 dependency, custom-accounting correctness, prepaying-router requirement, no admin keys post-deploy.

6 minDraft
Operations

Deployment & Configuration

Base mainnet addresses, CREATE2 salt mining for the hook permission bits, default fee & raw-buffer parameters.

5 minDraft
Operations

References & Reading

Uniswap v4 core & hooks, custom accounting, Aave v3, the Permit2 / Universal Router stack.

2 minLinks
Uniswap v4 · $REHYP · Technical Specification

The Rehyp Hook

A Uniswap v4 hook that is the $REHYP ERC-20. One contract, three asset pools, Aave-fed buybacks.

Draft · Working Document Last updated May 2026 v0.1

01Executive Summary

One Solidity contract is both the $REHYP ERC-20 and a Uniswap v4 hook. There are no LPs — the hook holds all inventory and quotes prices off a virtual constant-product curve. Idle asset reserves earn interest on Aave v3, and that interest is used to buy REHYP back along the curve and burn it.

$REHYP ships as a Uniswap v4 hook with hook-owned inventory. The same address is the ERC-20 token, the hook contract, and the counterparty to every swap. There are three asset pools on Base — WETH/REHYP, USDC/REHYP, GHO/REHYP — each routed through the same hook, each backed by its own Aave v3 aToken.

Because the design starts with no LP reserves, the hook uses Uniswap v4's custom-accounting path: beforeSwap returns a BeforeSwapDelta and settles input/output directly against the PoolManager rather than against an LP-provided curve. The asset side of each pool keeps a small raw buffer (default 20% of xReserve); everything above that target is supplied to Aave to earn interest. When a sell needs more asset than the raw buffer holds, the hook withdraws from Aave inside the same swap call.

Core Loop

Buy REHYP → asset flows in → excess auto-supplied to Aave. Sell REHYP → asset withdrawn from Aave on demand. Interest accrues on the asset side; harvestYield() buys REHYP with that interest and burns it. Supply only ever goes down.

Swapper WETH / USDC / GHO ↔ REHYP Rehyp Hook = $REHYP ERC-20 virtual CPMM raw buffer · 20% Aave v3 aWETH · aUSDC · aGHO interest accrues swap (prepaying router) aave.supply() harvestYield → buy & burn REHYP User Hook Yield Source

02Background & Primitives

2.1 Uniswap v4 Custom Accounting

Uniswap v4 lets a hook return a BeforeSwapDelta from beforeSwap, which credits or debits both sides of the swap directly against the PoolManager. The pool's own concentrated-liquidity reserves are bypassed entirely. This is the only way to launch with zero LP liquidity: the hook itself supplies the quote, takes the input, and settles the output.

Because the hook takes input via PoolManager.take() inside beforeSwap, swaps must be routed through a router that prepays the swap input into the PoolManager during its unlock callback — a normal v3-style router that settles input only after the swap will revert against a zero-reserve pool. On Base this works out of the box with the official v4 Universal Router via Permit2.

2.2 The Hook Address Is the Token

The contract implements both IHooks and the ERC-20 interface for $REHYP. currency1 in every pool key is the contract's own address. When the hook needs to release REHYP to a buyer it calls PoolManager.burn on an internal ERC-6909 claim balance, which credits the swapper's side of the swap delta with REHYP. There is never any ERC-20 transfer on the swap path.

2.3 Aave v3 aTokens as the Yield Source

The hook supplies excess asset balance into Aave v3 via IPool.supply and receives the corresponding aToken (aWETH, aUSDC, aGHO on Base). aTokens accrue interest in-place — the balance grows over time without any user action. On a sell that needs more asset than the raw buffer holds, the hook calls aave.withdraw directly into the PoolManager's expected target.

There is no Morpho integration. There is no Euler integration. There is one yield source per asset, and it is Aave v3.

03Architecture Overview

3.1 Component Map

ComponentRole
RehypHook.solOne contract: $REHYP ERC-20 + Uniswap v4 hook + Aave integration
assetPools[asset]Per-asset state: xReserve, xVirtual, yReserve, aToken, rawTargetBps
Aave v3 PoolExternal lending source — single integration, no ERC-4626 wrapper used
aToken (per asset)aWETH / aUSDC / aGHO — interest-bearing receipt held by the hook
v4 PoolManagerHolds REHYP claims (ERC-6909) seeded once at launch; settles all swap deltas
Universal Router + Permit2The required prepaying entry point for end-user swaps

3.2 The Three Pools

At deploy time the constructor accepts three PoolConfigInput entries. Each registers an asset with its aToken, its initial REHYP reserve (yReserve), its virtual asset reserve (xVirtual), and the raw-buffer target in basis points. The total of the three yReserve values is the entire $REHYP supply — 50,000,000 by default — minted once to the hook itself and never inflated.

PoolAsset (Base)aToken (Base)Default seed (REHYP)
WETH / REHYP0x4200…0006aWETH · 0xD4a0…8bb720,000,000
USDC / REHYP0x8335…2913aUSDC · 0x4e65…c0AB15,000,000
GHO / REHYP0x6Bb7…10EeaGHO · 0x067a…cBd115,000,000

3.3 Pool Key Constraints

Every pool initialised against this hook must use currency1 = address(this), fee = 0 (the LP fee path is unused), and tickSpacing = 1. Attempts to addLiquidity or donate revert with NoLP / NoDonate. Only buys and sells go through.

04Hook Logic in Detail

4.1 beforeInitialize — Register the Asset Pool

On PoolManager.initialize, the hook validates the pool key and records the resulting PoolId against the asset. Once initialised, a pool cannot be re-initialised. This is the only place where pool/asset identity is bound.

4.2 seedRehypClaims — One-Shot Inventory Seeding

After deployment the launch script calls seedRehypClaims() once. The hook unlocks the PoolManager, transfers its entire ERC-20 balance to the PoolManager, settles, and mints itself an equivalent ERC-6909 claim balance against its own currency. From that point on, releasing REHYP to a swap is a PoolManager.burn against the hook's claim, and receiving REHYP back from a sell is a PoolManager.mint.

4.3 beforeAddLiquidity / beforeRemoveLiquidity — Reject

Both revert with NoLP. There is no external liquidity provision. All inventory is hook-owned.

4.4 beforeSwap — Buys

A buy is zeroForOne = true: asset in, REHYP out. The hook quotes the buy against the virtual constant-product curve, takes the input asset out of the PoolManager via take(), deposits any amount above the raw-buffer target into Aave, and returns a BeforeSwapDelta that credits the swapper with REHYP.

if (params.zeroForOne) {
    fee       = amountIn * feeBps / BPS;
    amountOut = yReserve * (amountIn - fee) / (xReserve + xVirtual + amountIn - fee);
    poolManager.take(asset, address(this), amountIn);
    _depositExcessRaw(asset, pool);          // supply to Aave above target
    poolManager.burn(address(this), rehypId, amountOut); // release REHYP to swapper
}

4.5 beforeSwap — Sells

A sell is zeroForOne = false: REHYP in, asset out. The hook claims REHYP back from the PoolManager, then settles the asset side. If the raw balance is enough it transfers directly; otherwise it withdraws the shortfall from Aave straight to the PoolManager.

if (rawBalance >= amountOut) {
    IERC20(asset).safeTransfer(address(poolManager), amountOut);
    poolManager.settle();
} else {
    // transfer what we have, then top up from Aave
    uint256 shortfall = amountOut - rawBalance;
    aave.withdraw(asset, shortfall, address(poolManager));
    poolManager.settle();
}
Aave Rounding Tolerance

Aave occasionally returns one or two wei less than requested due to internal rounding. The hook tolerates a shortfall up to AAVE_ROUNDING_TOLERANCE by absorbing the difference into xReserve and emitting AaveRoundingShortfallAbsorbed. Anything larger reverts the swap.

4.6 rebalanceRaw — Push Excess Into Aave

Permissionless. Anyone can call rebalanceRaw(asset) to sweep any raw balance above the pool's rawTargetBps into Aave. The same routine runs automatically inside every buy and sell, so explicit calls are only useful when raw balance has accumulated outside the swap path.

05Yield Harvest & Burn

The single deflationary mechanism: Aave interest accrued on the asset side is treated as a virtual buyback input, used to consume REHYP from the curve, and then permanently burned.

5.1 Measuring Realised Yield

For each asset, the hook tracks xReserve as the principal it actually owes back to swappers. The real managed total is rawBalance + aTokenBalance. The delta between managed total and xReserve is realised yield:

managed       = IERC20(asset).balanceOf(this) + IERC20(aToken).balanceOf(this);
yieldAssets   = managed - pool.xReserve;          // must be > 0

5.2 Buying REHYP With Yield

harvestYield(asset) is permissionless. It quotes the yield amount as a buy on the curve — but at zero fee, since the buyer is the protocol itself — and burns the REHYP that would have been minted to a normal buyer:

rehypBurned = yReserve * yieldAssets / (xReserve + xVirtual + yieldAssets);
xReserve   += yieldAssets;                        // principal grows
yReserve   -= rehypBurned;                        // circulating supply drops
poolManager.unlock(UNLOCK_BURN_REHYP, rehypBurned);
totalRehypBurnedFromYield[asset] += rehypBurned;

The unlock path mirrors the seed: burn the claim against the PoolManager, clear the delta, and decrement totalSupply. The supply only ever moves in one direction.

5.3 Why It's Safe

Because the principal (xReserve) is reconciled against managed balance before any burn, a harvest can never reduce the asset-side cushion that swappers depend on. RehypReserveTooLow reverts before the burn if it would push yReserve below MIN_REHYP_RESERVE. Aave insolvency would manifest as aTokenBalance < xReserve, which makes managed - xReserve underflow-check revert — harvest fails, but no funds are at additional risk.

06Pricing Model

6.1 Virtual Constant Product

Each pool runs a standard x · y = k curve, but with a virtual offset on the asset side:

k = (xReserve + xVirtual) * yReserve

xVirtual is set at construction. It exists only as a number — no asset actually backs it — and serves to set the initial price without requiring a seed deposit. xReserve starts at zero and grows as buys arrive; xVirtual never changes.

6.2 Initial Price

With xReserve = 0, the spot price of one REHYP in asset units is xVirtual / yReserve. The launch script derives xVirtual from a target initial market cap in USD and a USD WAD for the asset:

xVirtual = (targetMarketCapUSD * 1e18 * 10**assetDecimals)
         / (totalSupply * assetUsdWad);

The default configuration targets a $10,000 initial market cap across 50M REHYP — an initial price of $0.0002 per REHYP, encoded separately into each pool's xVirtual based on that asset's USD price.

6.3 Fee

A single fee parameter applies to all three pools, default 30 bps (0.30%). Buy-side fees are subtracted from the asset input before quoting; sell-side fees are grossed up so that the swapper receives the requested net amount. The fee is retained inside the pool — there is no external fee recipient — so it grows xReserve and therefore counts toward future harvestable yield once supplied to Aave.

6.4 Quoting Helpers

For UIs and routers, four read-only quote helpers are exposed:

FunctionReturns
quoteBuy(asset, amountIn)amountOut, fee
quoteBuyExactOut(asset, amountOut)amountIn, fee
quoteSell(asset, amountIn)amountOut, fee
quoteSellExactOut(asset, amountOut)amountIn, fee

sellCap(asset) returns the maximum REHYP that can be sold given the current raw + Aave-withdrawable balance — useful for routers to detect a partial-fill scenario before submitting.

07Solidity Surface

Excerpts from src/RehypHook.sol. Refer to the repository for the full source.

7.1 State

struct AssetPool {
    bool    enabled;
    bool    initialized;
    address aToken;          // e.g. aWETH
    PoolId  poolId;
    uint256 xVirtual;        // constant; sets initial price
    uint256 xReserve;        // principal asset owed to swappers
    uint256 yReserve;        // circulating REHYP in this pool
    uint16  rawTargetBps;    // e.g. 2000 = keep 20% raw, lend the rest
}

mapping(address asset => AssetPool) public assetPools;
mapping(address asset => uint256) public totalYieldHarvested;
mapping(address asset => uint256) public totalRehypBurnedFromYield;

7.2 Hook Permission Bits

function getHookPermissions() public pure returns (Hooks.Permissions memory) {
    return Hooks.Permissions({
        beforeInitialize:           true,
        beforeAddLiquidity:         true,    // reverts: NoLP
        beforeRemoveLiquidity:      true,    // reverts: NoLP
        beforeSwap:                 true,
        beforeDonate:               true,    // reverts: NoDonate
        beforeSwapReturnDelta:      true,
        // everything else: false
    });
}

7.3 Public Read API

function poolView(address asset) external view returns (
    bool    initialized,
    PoolId  poolId,
    address aToken,
    uint256 xReserve,
    uint256 xVirtual,
    uint256 yReserve,
    uint256 rawAssets,
    uint256 aaveAssets,
    uint256 withdrawableAssets,
    uint256 harvestableYield
);

function sellCap(address asset) external view returns (uint256 rehypInMax);

7.4 Public Write API

function harvestYield(address asset)
    external returns (uint256 yieldAssets, uint256 rehypBurned);

function rebalanceRaw(address asset)
    external returns (uint256 deposited);

// One-shot at launch; permissionless
function seedRehypClaims() external returns (uint256 amount);

08The $REHYP Token

8.1 Supply

Fixed supply of 50,000,000 REHYP, minted once in the constructor — equal to the sum of the three pool seeds. The constructor is the only mint site. There is no owner-mint function, no governance mint, no upgradeability. Supply moves only in one direction, via harvestYield burns.

8.2 Custody Model

At launch the hook holds the entire supply as its own ERC-20 balance. seedRehypClaims() transfers all of it into the v4 PoolManager as an ERC-6909 claim balance against currency address(this). From that point, REHYP circulates only via swaps: a buy mints a swap-side credit that the router forwards to the swapper, and a sell takes it back.

8.3 Why REHYP Is Held by the Hook, Not Distributed

Because pricing is virtual-CPMM and there are no LPs, the hook itself is the counterparty. Distributing REHYP outside the swap path before launch would imbalance yReserve against the curve and break price discovery. Every REHYP in circulation entered through a buy at the curve's then-current price.

No admin keys

Fee bps, raw-target bps, xVirtual, aToken bindings and pool registrations are all set in the constructor and are immutable. There is no owner, no multisig, no pausing, no upgrade path. The only ongoing privileged action is harvestYield, and that is permissionless.

09Risk Analysis

RiskMitigation
Aave v3 insolvency or paused withdrawals on BaseSingle, well-known integration; sellCap exposes withdrawable headroom so routers can size accordingly; sells revert before partial fill
Custom-accounting correctnessFull v4 PoolManager integration test plus mainnet- and Base-fork tests against the official deployment
Router uses non-prepaying flowHook reverts on a normal v3-style router; documented requirement to use the v4 Universal Router (or any router that settles input during unlock)
Aave rounding produces under-withdrawalUp to AAVE_ROUNDING_TOLERANCE wei absorbed into xReserve; larger shortfalls revert the swap
Reentrancy via aToken / asset transferAll external token transfers settle through the v4 PoolManager lock; asset and aToken contracts on Base are non-reentrant ERC-20s
Hook permission-bit mismatch on deploymentCREATE2 salt-mining in DeployRehypHook.s.sol forces the required permission bits into the address; validateHookAddress() checks them post-deploy
Price manipulation via large in-block buy then sellSwapper pays fee both ways and round-trips the curve; sandwiches are an MEV cost for the user but cannot extract beyond standard CPMM bounds

10Deployment & Configuration

10.1 Launch Script

  1. CREATE2 mine an address with the correct hook permission flags (0x2aa8).
  2. Deploy RehypHook with the v4 PoolManager, Aave v3 Pool, fee bps, and three PoolConfigInput entries.
  3. Call seedRehypClaims() once to move the entire supply into the PoolManager.
  4. Call PoolManager.initialize three times — once each for WETH/REHYP, USDC/REHYP, GHO/REHYP — with fee = 0, tickSpacing = 1, and the initial sqrtPriceX96.

10.2 Default Parameters

ParameterDefault
feeBps30 (0.30% on every swap)
rawTargetBps2000 (keep 20% of xReserve raw; supply 80% to Aave)
totalSupply50_000_000e18
targetMarketCapUSD10_000 ($0.0002 / REHYP initial)
Pool seed (WETH / USDC / GHO)20M / 15M / 15M REHYP respectively
NetworkBase mainnet

10.3 Base Mainnet Addresses

ContractAddress
v4 PoolManager0x498581fF718922c3f8e6A244956aF099B2652b2b
Aave v3 Pool0xA238Dd80C259a72e81d7e4664a9801593F98d1c5
WETH0x4200000000000000000000000000000000000006
USDC0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
GHO0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee
Rehyp Hook · $REHYP0xa6BFdD21489C576B48585DC28D74AB79d0Af6aa8

11References & Further Reading

This document is a technical design specification for research and development purposes. It does not constitute financial or investment advice.