stETHer
Uniswap v4 hook implementing dynamic fees and proper rebasing token handling
Problem Statement
I created a new type of AMM that works completely differently from traditional pools. Instead of the usual x*y=k curve that causes slippage, I use x+y=k which enables perfect 1:1 swaps when the pool is balanced.The magic happens with my dynamic fee system - I charge zero fees for ETH→stETH swaps (encouraging staking) but apply increasing fees for stETH→ETH swaps as the pool gets imbalanced. This naturally keeps the pool stable while generating revenue that funds incentives to bring it back into balance.The pool also properly handles rebasing tokens like stETH, so liquidity providers don't lose their staking yield just because they're providing liquidity.
Solution
The core innovation is using x + y = k instead of the traditional x * y = k formula. This means when the pool is balanced, you can swap 100 ETH for exactly 100 stETH with zero slippage - something impossible with regular AMMs.I implemented this as a Uniswap v4 hook that intercepts swaps and applies my custom logic. The fee structure is intentionally asymmetric:ETH → stETH: Always 0% (I want to encourage staking) stETH → ETH: Dynamic fees that increase as the pool gets unbalancedDynamic Fee TiersThe fees automatically adjust based on how much ETH is left in the pool:Pool has 70-80% ETH: 0.1% fee (balanced, low fee) Pool has 60-70% ETH: 0.5% fee (slightly unbalanced) Pool has 50-60% ETH: 1.0% fee (getting concerning) Pool has 40-50% ETH: 2.0% fee (significantly unbalanced) Pool has <40% ETH: 5.0% fee (emergency mode)This creates natural economic pressure to keep the pool balanced - as ETH gets scarce, it becomes more expensive to withdraw, which encourages people to deposit more ETH instead. Rebasing Token SupportOne of the trickiest parts was handling stETH properly. Regular AMMs break when you add rebasing tokens because the balances change over time. I solved this with a shares-based accounting system that preserves the underlying yield.My test stETH implementation gives 5% APY, and crucially, LPs don't lose this yield when they provide liquidity. The rebasing happens continuously based on time elapsed. LP Token SystemI built a proper ERC20 LP token that represents your share of the pool. When you add liquidity, you get LP tokens. When you remove liquidity, you burn your LP tokens and get back your proportional share of the pool PLUS any fees that accumulated while you were providing liquidity.The cool part is that fees automatically compound - instead of needing to manually claim them, they just increase the value of your LP position over time. Revenue SharingHere's where it gets interesting economically. When fees are collected, they're split:90% goes to liquidity providers (you earn fees for providing liquidity) 10% goes to the protocolBut here's the clever bit - those protocol fees don't just sit there. They fund incentives for ETH→stETH swaps. So when the pool gets unbalanced (too much stETH, not enough ETH), we can use the accumulated protocol fees to give people a small bonus for depositing ETH. The Self-Balancing LoopThis creates a beautiful self-balancing system:Pool gets unbalanced (too much stETH) stETH→ETH swaps become more expensive (higher fees) Higher fees generate more protocol revenue Protocol revenue funds incentives for ETH deposits People deposit ETH to get the bonus Pool rebalances naturallyThe system is completely sustainable because it only spends what it earns.Self-Balancing: Incentives funded by fees collected from the opposite direction Rate Limiting: Incentives capped at 0.1% and only when sufficient protocol fees exist Sustainability: System only spends what it earns, ensuring long-term viabilityTechnical Features Smart Contract ComponentsMain Pool Contract (Counter.sol): Core AMM logic and Uniswap v4 hook integration LP Token (ConstantSumLP.sol): ERC20 token for liquidity provider shares Revenue Manager (RevenueManager.sol): Fee calculation and distribution Rebasing Token (StETH.sol): Mock stETH with 5% APY for testingKey FunctionsaddLiquidity(): Add liquidity and receive LP tokens removeLiquidity(): Burn LP tokens and withdraw assets + accumulated fees beforeSwap(): Uniswap v4 hook that implements constant-sum swaps with dynamic fees claimFees(): Allow LPs to claim accumulated fees rebase(): Update stETH balances based on time-based yieldTesting Suite74 Tests Total covering all functionality Unit Tests: Individual contract functionality Rebasing Tests: Time-based yield mechanics Fee Distribution Tests: Multi-LP scenarios
Hackathon
ETHGlobal New York 2025
2025
Prizes
- 🏆
v4 Hooks on Unichain3rd place
Uniswap Foundation
Contributors
- mcmoodoo
77 contributions