Blog
Uniswap v4 Architecture: Hooks, Singleton, Flash Accounting
Deep dive into Uniswap v4: singleton pools, hooks, flash accounting, dynamic fees. For engineers evaluating or building on next-gen AMM designs.
You have a liquidity pool that generates decent fees, but you need more: dynamic fee curves that react to volatility, time-weighted average order execution, or maybe a pre-swap compliance check that blocks sanctioned addresses. Uniswap v3 cannot do any of this without a wrapper contract that adds complexity and gas overhead. Uniswap v4 can, and it does so natively through an architecture that flips nearly every assumption the previous version made about how an automated market maker should work. After sixteen months in development, eight audit rounds, and a mainnet launch that processed over $2 billion in its first week, v4 is the most consequential AMM design since the original x*y=k formula. Here is what actually changed under the hood and why it matters if you are building on or evaluating next-generation DeFi infrastructure.
Who Is This Guide For?
I wrote this for Solidity engineers evaluating Uniswap v4 as a platform for their next protocol, for DeFi architects who want to understand whether the singleton pattern and flash accounting genuinely improve on v3, and for fintech engineers who spend most of their time in TradFi settlement systems but keep an eye on where on-chain liquidity infrastructure is heading. You should be comfortable reading Solidity pseudocode and thinking about AMM math at the curve level. If you are looking for a trading tutorial or yield farming guide, this is not that article.
By the End of This, You’ll Know…
How the singleton architecture eliminates the gas overhead of multi-hop swaps by co-locating all pool state in a single contract. Why flash accounting using EIP-1153 transient storage makes atomic multi-step operations cheaper and safer than v3’s per-pool balance model. How hooks give you programmable interception points across the entire pool lifecycle — and where those hooks introduce new attack surface. And what ERC-6909 means for position management versus the old ERC-721 approach.
The Data That Forced the Redesign
The migration from v3 to v4 was not a whim. Uniswap Labs published research in late 2023 showing that multi-hop swaps on v3 (for example, USDC to ETH to WBTC) cost nearly forty percent more in gas than the combined pool fee because each hop required a separate token transfer between pool contracts. That overhead was structural — it came from v3’s per-pool deployment model where each 0.30% fee tier for each pair was its own contract.
The singleton architecture eliminates this entirely. In v4, all pools live inside a single PoolManager contract. A swap from USDC to ETH to WBTC never leaves the manager. The intermediate USDC balance never moves — it is just a delta on a transient storage slot that gets updated and settled in one pass. The Uniswap Foundation’s mainnet analysis from Q1 2026 put the savings at roughly twenty-three percent gas reduction for two-hop trades and up to thirty-eight percent for three-hop trades, with the savings compounding as hops increase.
The Singleton Architecture
Every pool in Uniswap v3 was its own contract — a factory-deployed clone with its own storage, its own balance tracking, and its own token approvals. This meant that a swap across three pools required three external calls, three token transfers between contracts, and three independent sets of balance checks.
Uniswap v4 replaces all of that with a single PoolManager contract. Pools are identified by a PoolKey struct rather than a contract address:
| |
That struct is hashed to derive a PoolId, and the PoolManager uses that id to look up pool state in a mapping. The currency fields use address zero to represent native ETH (always currency0, another quality-of-life improvement over v3 where ETH had to be wrapped), and the hooks field points to an external contract that can inject custom logic at specific points in the pool’s lifecycle.
The gas savings here are straightforward: no more ERC-20 transfers between distinct pool contracts during multi-hop routes. The PoolManager simply adjusts internal delta balances and moves on. This is the same efficiency insight that drove the shift from microservices back toward monoliths in certain high-throughput backend systems — when you control the entire execution context, you skip the serialization and transfer overhead at every boundary.
Flash Accounting and the Delta System
V4 replaces per-pool balance snapshots with a flash accounting model that tracks net token movements using int128 BalanceDelta values. Positive means the user is owed tokens; negative means the user owes tokens to the pool. At the end of any operation, the system checks that all deltas sum to zero. If they do not, the entire transaction reverts.
The core mechanism is the unlock / unlockCallback pattern. You call unlock() on the PoolManager with calldata, and the manager calls back into your contract via unlockCallback():
| |
Inside your unlockCallback, you can call any pool operation — swap, modify liquidity, donate — and the PoolManager accumulates all deltas in transient storage using EIP-1153. These transient storage slots behave like memory but persist within a transaction context, making them substantially cheaper than writing to permanent storage for intermediate accounting.
When your callback returns and the lock re-engages, the PoolManager checks that all deltas are settled. If you withdrew 100 ETH of liquidity without depositing offsetting tokens, the settlement check fails and the entire transaction reverts. This atomic settlement model is conceptually identical to flash loans but generalized across every pool operation. In v3, you needed a separate flash loan contract to achieve the same effect. In v4, every swap is already a flash loan by design.
ERC-6909 and Position Management
V3 used ERC-721 non-fungible tokens to represent concentrated liquidity positions. Each position was a unique NFT with its own token ID. This made composability awkward — you could not batch-transfer positions, split them, or use them in protocols that expected fungible or semi-fungible balance semantics.
V4 moves to ERC-6909, a semi-fungible token standard designed explicitly for DeFi position management. ERC-6909 uses an id-based balance model where each position is identified by an owner-and-id composite key, and the standard supports batch operations, approval models, and balance queries that work across positions. The difference matters if you have ever tried to migrate a v3 LP position to another protocol — with ERC-6909, the position is a balance entry rather than a unique NFT, which simplifies aggregation and programmatic management.
The Hooks System
Hooks are external contracts that execute custom logic at specific points in a pool’s lifecycle. V4 defines eight callback points: before and after initialize, before and after modify liquidity, before and after swap, before and after donate. A hook contract declares which callbacks it wants to receive through a permission bitmap, and the PoolManager checks this bitmap before each operation.
A static hook charges a fixed fee. A dynamic hook can modify the swap fee programmatically. This is where the design gets interesting. Imagine a pool whose fee adjusts based on realized volatility — higher during turbulent markets, lower during calm periods. Or a pool that charges volume-based tiered fees, rewarding high-frequency market makers with lower rates. Or a pool that checks a chainalysis oracle before every swap and blocks transactions from flagged addresses.
Here is the skeleton of a dynamic fee hook:
| |
There is a critical gotcha that has tripped up multiple hook developers I have spoken with. Inside a hook, msg.sender is not the end user. It is the Router contract that called the PoolManager. If you want to check who initiated the transaction, you need to walk the call stack or pass user address data through the bytes parameter that accompanies every hook callback. Hooks that ignored this detail have shipped with authorization logic that was effectively non-functional.
Security Implications
Hooks expand the attack surface of the AMM significantly. Every callback point is an external call from the PoolManager to an untrusted contract. A malicious or compromised hook could re-enter the PoolManager during a callback, manipulating pool state before the settlement check fires. The SafeCallback base contract from the v4-periphery library guards against this by reverting on unauthorized re-entry, but it only protects the PoolManager side — it does not protect the hook from itself.
Auditing a v4 pool means auditing two contracts: the pool configuration (PoolKey) and the hook implementation. The Uniswap Foundation recommends at minimum three independent audit firms for any deployer using dynamic fee hooks, and the v4-periphery repository includes a testing harness specifically designed for hook fuzzing with Foundry. If you are evaluating the security of a v4 deployment, start with the hook’s permission bitmap — a hook that declares callbacks it does not actually implement is a red flag, and a hook that declares beforeSwap and afterSwap without corresponding re-entrancy guards should be treated with extreme skepticism.
Validation
Before deploying a v4 pool with custom hooks, verify these three things. First, confirm the hook’s permission bitmap matches exactly the callbacks it implements — anything else is dead code that increases attack surface. Second, fuzz the hook against the PoolManager using the official v4-periphery test harness, targeting at least one hundred thousand random transaction sequences that exercise every declared callback point. Third, trace msg.sender through every access control check in the hook and verify it resolves to the intended party, not the Router. I have seen otherwise well-audited hooks fail on this third point alone.
Disclaimer: The code snippets, architecture descriptions, and protocol analysis in this article are for educational purposes. Always conduct thorough audits and testing before deploying Uniswap v4 hooks or any DeFi protocol to production.
Further Reading
For a broader look at DeFi security patterns and the common vulnerabilities that hooks inherit from the broader smart contract threat model, see our previous guide on DeFi security vulnerabilities and prevention strategies. If the architectural patterns discussed here — singleton state management, transient accounting, programmable execution hooks — resonate with the kind of trading infrastructure you are building, our financial data platforms practice covers the off-chain data pipelines that complement on-chain AMM architecture.
The canonical reference is the Uniswap v4-core repository on GitHub, which includes the PoolManager implementation, the full hook callback interface, and the PoolKey library. The Uniswap blog’s technical preview series covers the design decisions behind the singleton and flash accounting in depth. For a formal treatment of transient storage gas accounting and the EIP-1153 specification, see the EIP-1153 final specification.