Architecture
Explore the contracts behind Uniswap v4 permissioned pools, including the Permissions Adapter, hooks, position manager, and routing.
Permissioned pools are built from four contracts that work together to enforce an issuer's allowlist while keeping the permissioned token compatible with the standard PoolManager.
The Permissions Adapter
The Permissions Adapter is the ERC-20 wrapper contract at the center of this design. It holds the underlying permissioned token and mints a wrapped representation that the pool trades, so the underlying token never enters the PoolManager directly. The adapter and the wrapped token are the same contract.
Wrapping and unwrapping are handled automatically. Swappers and liquidity providers interact with the token as usual, and the router and position manager wrap and unwrap behind the scenes, so end users never manage the wrapped representation themselves. Wrapping is necessary for two reasons:
- The
PoolManagerallowlist cannot be enforced directly. ThePoolManageris a single shared contract, so it cannot be added to every issuer's allowlist. The adapter acts as the approved holder of the underlying token and keeps the raw asset out of theÂPoolManager. - Direct holding would expose the token as a freely tradable claim. A permissioned token held directly by the
PoolManagercould be minted into an ERC-6909 claim and traded without the allowlist. The adapter prevents this by restricting minting to authorized periphery contracts, such as the position manager, router, and quoters the issuer approves.
See the PermissionsAdapter source in v4-periphery.
- Pool manager exclusivity: only the
PoolManagercan hold the wrapped token. When it is transferred out of the pool, the adapter burns it and releases the underlying token in the same call. - Pluggable allowlist: the adapter delegates permission checks to an allowlist checker that the issuer implements and deploys.
The adapter exposes several administrative functions for the permissioned token issuer:
updateAllowListChecker: update the pluggable validation contract that decides who is authorized to swap the token or provide liquidity.updateAllowedWrapper: approve or revoke a contract, such as a router, position manager, or quoter, that can wrap the token.updateSwappingEnabled: enable, pause, or resume swapping for the token. Swapping is disabled by default on a new adapter.setAllowedHook(on the Permissioned Position Manager, callable only by the adapter owner): allow or revoke a hook for the adapter currency. Position mints and liquidity increases revert withInvalidHookunless the pool's hook is allowed.
Permissioned Hooks
The permissioned hook enforces the allowlist on every interaction. Like any v4 hook, it is attached to a pool at initialization through the PoolKey. It activates four callbacks:
beforeInitializequeries thePermissionsAdapterFactory, requires at least one pool currency to be a factory-verified adapter, and rejects any currency that is an unverified adapter, so a pool cannot be created around an unverified wrapper.beforeSwapchecks theSWAP_ALLOWEDflag for the swapper, and also reverts while the issuer has swapping paused viaÂupdateSwappingEnabled.afterSwapemits aSwapevent so indexers can track activity on permissioned pools.beforeAddLiquiditychecks theLIQUIDITY_ALLOWEDflag before a position is minted.
Permissions are expressed as flags: SWAP_ALLOWED (0x0001) and LIQUIDITY_ALLOWED (0x0002). The hook also confirms that the calling router or position manager is an approved wrapper, which is why the issuer must approve the contracts that can interact with the pool.
Permissioned Position Manager
The Permissioned Position Manager extends the standard PositionManager and adds allowlist enforcement and wrapping.
- Non-transferable NFTs: position transfers revert, which prevents an allowlisted holder from handing a position to a disallowed address.
- Position unwinding: the owner of either Permissions Adapter in the pool can call
unwindPositionto burn a position NFT, remove its liquidity, and route each asset back to the holder. Any asset the holder can no longer receive falls back to that asset's own issuer (as tokens, or as an ERC-6909 claim if delivery fails), so unwinding never lets one issuer receive the other's asset. - Automatic wrapping: the position manager wraps the permissioned token before interacting with the pool and validates the holder against the allowlist on mint and increase.
When building a pool key, supply the adapter address as the currency, not the underlying permissioned token. The same applies when settling and taking.
When a position is unwound, each asset routes to the holder first. An asset the holder can no longer receive falls back to its own issuer, never to the other issuer.
Swap Routing
Swaps go through the Universal Router, which handles the wrapping and unwrapping of permissioned tokens. The router identifies the permissioned token in the swap path, wraps it before the pool interaction, executes the swap with the wrapped token, and unwraps automatically on exit. The allowlist is enforced twice: by the router when it wraps the input token, and by the hook on beforeSwap, so the restriction cannot be bypassed.
Permissioned swap routing requires Universal Router 2.2.0 or higher.
Adapter Verification
A factory deploys and verifies adapters. Verification confirms that an adapter is allowed to hold its underlying token: the issuer seeds the adapter with a minimal balance, as little as 1 wei, which is only possible if the adapter is on the token's allowlist. See Step 3 and Step 4 for the mechanics. The factory records a mapping from each adapter to its underlying token, never the reverse.
Factory verification is separate from the ERC-165 check on the allowlist checker. Factory verification proves the adapter holds a real balance of its token, while ERC-165 only confirms that a checker implements IAllowlistChecker.
Security Considerations
- Issuer recall: if a holder loses permissions, the Permissions Adapter owner can call
unwindPositionto remove their liquidity and route the assets back. Assets that cannot be delivered to the holder fall back to the issuer, so an issuer can always reclaim exposure to a permissioned token when required. - Non-custodial design: user funds can only leave the pool through
PoolManagersettlement flows: swaps, position withdrawals, and claim redemptions. They never leave through the wrapped token directly. - Access control: the Permissions Adapter owner can change the allowlist checker, approve or revoke wrappers, and pause swapping. The owner cannot transfer positions or pull funds directly through the wrapped token; unwinding routes assets to the holder first, and the issuer receives an asset only when the holder can no longer hold it. The factory and hook are shared contracts that Uniswap deploys, and they are not issuer-controlled.
- Reverse mapping: the factory maps each adapter to its underlying token, never the reverse, which stops anyone from registering an arbitrary allowlist check against an existing ERC-20.
- Unwinding in dual-permissioned pools: pools with two permissioned tokens from different issuers, for example two tokenized funds in the same sector, are fully supported. Either Permissions Adapter owner can unwind a position, and each asset routes to the holder first. An asset the holder can no longer receive falls back to its own issuer only, so one issuer cannot seize the other's asset.
Where to Go Next
- Onboard a token in Deploy a Permissioned Pool.
- Integrate permissioned tokens in an app with Swapping on Tokenized Pools.
- Review hook fundamentals in Hooks.