Learn what to watch out for and what to take care of when integrating with Uniswap v4.
Vision behind Uniswap V4 and team approach
The largest DEX introduces another innovation. Even though the main focus of the new version is on the gas efficiency, it undoubtedly significantly increases the flexibility and possibilities of developers integrating and building on top of Uniswap.
There are three main changes in V4:
- singleton, and
- native ETH support.
Thanks to the introduced hooks and some other cool stuff that we will discuss in this article, builders will be able to operate in very different ways, competing with each other for the attention of users.
Previously, they tried to define a safe framework and assumptions in line with their vision. Now, they are open to the visions of others and want to be surprised by applications that they did not come up with on their own.
While the Uniswap v3 was introduced suddenly and unexpectedly, this one is introduced slowly and carefully. Thanks to this, the code can be reviewed by more people, feedback submitted and doubts dispelled.
This is definitely an approach we applaud and encourage others to follow.
Let this article be our small contribution to secure integrations with the Uniswap v4 smart contracts so that developers are aware of the risks that should be taken care of and minimized.
Uniswap v3 vs Uniswap v4
|Feature||Uniswap v3||Uniswap v4|
|Architecture||pools deployed by factory||singleton-style architecture|
|Pool Creation Cost||higher due to factory model||lower due to singleton model|
|Swap and Withdrawal Fees||fixed||fixed plus managed by hook contracts|
|Native ETH support||no||yes|
|Custom Functionality via Hooks||no||yes|
|Accounting||standard ERC20||ERC1155 & flash accounting|
|Interaction||direct or indirect through routers||indirect through locker|
Uniswap v4 architecture
The architecture is significantly different from the previous version. Above all, it uses a singleton-style architecture. That means that all pool state is managed in the one smart contract (PoolManager) and the factory no longer exists as there is no deployment of new contracts. This is the first gas optimization that reduces creation of a pool by 99%.
The second big change is the introduction of hooks that can be called at the following moments:
- beforeInitialize, afterInitialize,
- beforeModifyPosition, afterModifyPosition,
- beforeSwap, afterSwap,
- beforeDonate, afterDonate.
The one thing that is new on the list is the donation. It is simply used to donate some amounts to be distributed as fees.
This is a huge change to the business logic of the pools. By injecting these hooks, the developers are able to create pools that support such use cases as:
- TWAMM for handling large swap orders without price impact,
- dynamic fees,
- custom oracle implementations,
- and many more.
However, there is a limitation for the hooks - they cannot be added or removed after the pool is initialized. Whenever the hook is turned on during the initialization, it cannot be turned off (and the opposite) because the hook activation flag is kept in the immutable key of the pool.
The specific consequence of the hooks, but also partially handled directly by the pool manager, are fees. The pools support two types of fees: swap fee and withdraw fee.
The swap fee can be defined as static, placed in the hook address, or dynamic, retrieved from the hook contract during the swap process. In both situations, the fee cannot be greater than 1%. After the swap fee is calculated, it is distributed between the protocol and the hook contract. Each component can specify what portion of the remaining fee they want, but the protocol is always first (the 25% is the highest percentage available for protocol). The distribution percentages can be updated at any moment. However, it does not change the swap fee.
The withdrawal fee is accounted for only if the hook has it specified. Similar to the swap fee, this fee is also distributed between protocol and hook contract and can be updated at any moment, indirectly via hook contract.
The last, but not least change is the architectural change that simply does not allow EOAs to use the pools directly, but only through the so-called router contracts. This is due to the lock functionality that opens the path for flash accounting.
The Uniswap v4 requires anyone who interacts with it to firstly call the lock function and execute all other operations in a callback function. What is new is that during the callback call, tokens can be used for any number of operations inside and outside the singleton and tokens from all pools are available.
That change opens a wide field for routers that, together with hooks, can build complex systems on top of Uniswap v4. Additionally, the account abstraction can only leverage that.
If you are not familiar with account abstraction, check out our previous article.
Threat modeling for Uniswap v4
The threat modeling can be simply divided into the following stages:
- drawing a diagram
- identifying key assets,
- identifying threat actors,
- determining how the threat actors could try to access key assets.
If the above stages do not sound clear for you, you must check our guide on threat modeling.
The diagram should include:
- components - smart contracts,
- business core functionalities - the most important functions of a smart contract that are used in the main business flow,
- roles - all users participating in the system with various rights (governance, owner, user, team member, etc.).
Here is a simple diagram of the Uniswap v4 that includes an external router:
The straightforward key assets in the Uniswap v4 are tokens kept by the pools. As Uniswap v4 brings back native ETH to the pools, Ether is also the key asset.
One could think of some special powers in the protocol, like overtaking the governance, however Uniswap v4 is permissionless so it has no governance… or does it? There is one special owner role for the protocol that can set the current protocol fee controller, so it is important to identify such ones as well. Nonetheless, a potential attacker would also for sure like to be able to take control of the hook or the router (which is an external component).
- Funds held by pools (tokens and Ether),
- Control the fee controller,
- Control over the hook,
- Control over the router.
First easy step to identify potential attackers, called threat actors in threat modeling nomenclature, is to take all the actors from the diagram. That gives a list of four threat actors.
- Hook Owner
- Protocol Owner
- Router Owner
You could add a “malicious” prefix to all of them just to make sure they are the potential attackers, but after a few threat modeling sessions you will stop doing that ;)
The third step is to combine the threat actors and the key assets and change the mindset to hacker's. You need to think how any actor could try to achieve any key asset.
Remember to not verify now whether it is possible, just write down what comes to your mind!
Another important thing to remember is that some of the threats are common, either for a specific type of contract or for the Web3 apps themselves. You can cover them with ready to use BTMs (Base Threat Models) not to reinvent the wheel.
We have covered threats for selected types of contracts in SCSVS. For example, if you are building a vault, you can check out the C4: Vault category for its common threats and if you are integrating with an oracle, check out the I3: Oracle category.
In this article I have focused on specific threats for the Uniswap v4 protocol and have grouped them by the components.
In Uniswap v4 hooks are an integral part of the pools (optional however) and are the new feature so this is where a lot of focus would go. They seem to have a lot of power as they are injected in multiple places, specify fees and hold some of the funds (fees).
- Upgradeable hook
- Hook Owner upgrades the hook and changes its logic to block selected operations.
- A malicious user exploits an upgradeability vulnerability to upgrade the hook (destroy or change logic).
- Denial of Service
- A hook starts to revert on calls after users have provided liquidity DoSing the protocol.
- A hook sets huge fees (possibly front-running the swaps and withdrawals).
- Hook Owner cannot collect fees due to the lack of that functionality.
- A malicious user exploits an access control vulnerability to collect hook’s fees.
- A hook performs a sandwiching attack on the swap to MEV the user.
- A hook performs a front-running attack during the modification of the position to change the withdrawable amounts.
- Access control
- A malicious user bypasses access control and takes over the hook to update params.
- External calls
- The hook gets a price from the external oracle that can be manipulated.
- The hook calls an external contract that can revert and DoS the hook (DoS forwarded to Uniswap v4 pool).
- The hook calls an external contract that is upgradeable and can be self-destructed (DoS the hook and the pool).
As the pool manager contains all assets managed by all pools, it is the main aim of the potential attacks, either direct or through other components.
- Flash accounting
- A malicious user bypasses the flash accounting invariants (introduced by locking mechanism) and steals tokens.
- Native ETH
- Re-entrancy attack using the transfer of native cryptocurrency.
Protocol Fee Controller
- Denial of service
- Protocol Fee Controller reverts on fetching fees DoSing the protocol.
- Protocol Owner sets huge protocol fees via protocol fee controller (possibly front-running the swaps and withdrawals).
Last, but not least and might look out of scope as this is not part of Uniswap v4. Nonetheless, Uniswap v4 requires users to use some contracts to interact, therefore I decided to include it in the threat modeling.
I have named this component a router because that is the most common type of a contract that users use to interact with Uniswap pools. However, this might be actually any application that interacts with Uniswap v4 on behalf of the user, but - what is important - user would have to approve it or transfer Ether to it.
- Upgradeable router
- Router owner upgrades the router contract and steals users’ assets.
- Malicious user exploits an upgradeability vulnerability and upgrades it to steal users’ assets.
- Unlimited approvals
- Router owner abusing unlimited approvals for the router.
- Malicious user exploits an access control vulnerability to abuse unlimited approvals.
Uniswap v4 secure integration
Not all of the threats are easily verifiable and mitigated. For some of them you have to minimize and accept the risk.
If you plan to integrate with Uniswap v4, make sure that you have addressed all threats mentioned above. Those can differ if you are building a hook, router (or other kind of locker contract) or other kind of application integrating with existing routers and pools with hooks.
Depending on the part that you are building you should either verify how you address those threats or how the components that you integrate with (e.g. existing hooks or routers) address them.
The basic list of security requirements for the builder or a hook:
- Make sure that you can collect the fees.
- Be transparent about the hook’s functionality:
- Build immutable hooks (no upgradeability).
- Implement limits for the hook fees.
- Make sure you have no unintended reverts in the hook.
The basic list of security requirements for the user of a pool or integration:
Perform the security review of the router:
- Make sure it cannot front-run you.
- Make sure that it is not upgradeable.
- Make sure it does not require unlimited approvals by default.
Perform the security review of the hook:
- Check its code and make sure it is immutable (no upgradeability).
- Make sure it is not dependent on other contracts (external calls) that can introduce vulnerabilities (price manipulation, reverts leading to DoS).
- Make sure it cannot increase the fees instantly and without limits.
- Make sure it cannot be updated to revert on pool operations and DoS the pool.
Did you like the article? Share it on social media!
Composable Security 🇵🇱⛓️ is a Polish company specializing in increasing the security of projects based on smart contracts written in Solidity. Examples of projects that have trusted us are market leaders such as FujiDAO, Enjin, or Tellor. We are creators of the Smart Contract Security Verification Standard. Speakers at various conferences such as EthCC, ETHWarsaw, or OWASP AppSec EU. Authors of numerous publications on DeFi security. Experienced auditors operating in the IT Security space since 2016.
If you need support in the field of security or auditing smart contracts do not hesitate to contact us.
About the author
PhD, Speaker, Co-Author of SCSVS and White Hat. Professionally dealing with security since 2009, contributing to the crypto space since 2017. Smart contract security research lead.