January 20, 2025

Uniswap v4 Audits: What We Learned About DeFi Security

Uniswap v4 is the latest evolution in decentralized exchanges, introducing transformative features like hooks and a unified pool structure to redefine automated market makers (AMMs). With innovation comes complexity, demanding rigorous security audits. 

To fortify its design, Uniswap Labs engaged four top security firms: OpenZeppelin, Spearbit, Trail of Bits, and Certora. These teams identified vulnerabilities ranging from critical risks that could jeopardize user funds to minor inefficiencies that could degrade performance.

In this article, we highlight three standout findings, assess their implications, and draw essential lessons for securing advanced DeFi systems.

Audit Overview

The table below summarizes the participating audit teams, the timeline of their evaluations, and the number of issues identified. Readers are encouraged to review the linked reports for detailed findings.

OpenZeppelin

  • Bugs found: 7
  • Start: July 2024

Certora

  • Bugs found: 5
  • Start: July 2024

Spearbit

  • Bugs found: 6
  • Start: Sep 2024

Trail of Bits

  • Bugs Found: 1
  • Start: Sep 2024

Breaking Down the Most Critical Bugs in Uniswap v4 

Let's look at three major bugs that were found during the above audits, figure out why they happen, and learn ways to make more reliable protocols.

  1. Double Counting of Deposits on CELO

OpenZeppelin identified a critical vulnerability on the CELO blockchain that could allow attackers to exploit Uniswap’s accounting mechanism. This vulnerability is deemed necessary because it allows attackers to withdraw more funds than they deposit, effectively enabling theft from the protocol. 

Such a flaw threatens the platform's financial stability, potentially leading to a total depletion of liquidity if exploited at scale. This vulnerability arises from the unique way CELO’s native token interacts with its ERC-20 counterpart, enabling double withdrawals and potentially draining the protocol.

Understanding the Bug

Uniswap’s accounting operates by tracking the balance delta for tokens. It includes three key functions:

  1. sync: Records the current token balance.
  2. settle: Computes the balance delta (the change in token balance) and credits the user.
  3. take: Allows users to withdraw their credited tokens.

On CELO, the protocol mistakenly credits deposits for both the native token and its ERC-20 representation, creating a loophole for attackers.

Bug Exploitation Scenario

  1. Sync with ERC-20 Token: The attacker calls the sync function with the CELO ERC-20 token to record the balance.
  2. Sync with Native Token: The attacker calls the sync function with the native  CELO token to record the balance.
  3. Transfer: Transfer funds from the attacker to the protocol in Celo’s native token, which is the same as the ERC20.
  4. Settle with Native Token: The attacker deposits CELO’s native token (amount X), which credits the user’s account with X tokens.
  5. Settle with ERC-20 Token
    Without any additional transfer, the attacker calls settle again using the ERC-20 token. The system erroneously credits another X tokens.
  6. Double Withdrawal via take
  • Call the take function with the CELO ERC-20 token to withdraw X tokens, reducing the ERC-20 token delta to zero.
  • Call the take function with the native CELO token to withdraw another X token, reducing the native token delta to zero.

Implications
The attacker withdraws 2X tokens after depositing only X, repeating the process to drain the pool from Celo’s ERC20 token. 

Why This Happens

This vulnerability stems from Uniswap’s inability to differentiate between CELO’s native token and its ERC-20 representation. This edge case is specific to CELO and would be infeasible on blockchains with standard native token handling.

Takeaway

Developers must account for edge cases involving non-standard tokens and blockchain-specific quirks, particularly when designing multi-chain protocols.

Specifically for this scenario, keeping the user’s flow to be as simple as possible prevents unintended consequences. In this exploit’s case, the user should not be able to sync twice without settling in between, which was the mitigation of this bug.

2. Tick Price Invariant Violation

Certora uncovered a medium-severity vulnerability in Uniswap v4 using formal verification. This approach employs mathematical proofs to verify that protocol logic behaves as intended under all scenarios. 

By rigorously analyzing the code, formal verification is particularly effective at uncovering subtle bugs that might evade conventional testing methods. Formal verification is a mathematical approach to proving the correctness of protocol logic, which makes it effective for uncovering subtle bugs.

Understanding the Bug

The issue arises when a critical invariant linking tick prices and pool state variables is violated, leading to potential fund misallocations.

In Uniswap v4, each pool maintains two key variables:

  1. pool.tick: Represents the current tick of the pool.
  2. pool.sqrtPrice: Represents the square root of the pool's current price.

The protocol guarantees that these variables adhere to the following invariant:

tickAtSqrtRatio(pool.sqrtPrice) == pool.tick

This invariant ensures consistency between the pool’s tick and its price, allowing the system to maintain accurate calculations during swaps. However, during our formal verification of this invariant using the Certora Prover, we uncovered a scenario where this guarantee was violated.

Bug Exploitation Scenario

  1. The attacker initiates a swap that depletes the liquidity associated with the current tick and crosses over to the next ticks.
  2. The protocol updates the pool.tick to the next tick without correctly adjusting pool.sqrtPrice.
  3. This results in a mismatch in where pool.sqrtPrice no longer aligns with the updated pool.tick.

Implications:

  • Misallocation of Funds: Incorrect price readings may lead to donations being sent to the wrong tick, causing a misallocation of assets.
  • External Misinterpretation: Observers querying the pool state would see a misaligned tick and price, potentially leading to incorrect assumptions about the pool’s health or behavior.

Why This Happens

The issue arises due to the complexity of accurately updating multiple state variables in tandem during edge cases like fully depleting a tick. While the Uniswap team acknowledged the correctness of our invariant, its violation revealed a subtle oversight in the implementation.

Takeaway

When defining invariants, developers must use the protocol’s design principles to uncover hidden edge cases and ensure the system’s behavior is aligned with the intended behavior.


3. Collected Protocol Fees During Swap

Trail of Bits identified a low-severity issue where invoking the collectFees function during a swap interferes with balance tracking, potentially reducing user payouts or causing transaction failures.

Understanding the Bug

Uniswap v4 allows users to call various functions during transactions, including those for collecting protocol fees. However, calling collectFees balance deltas are modified during an active swap, temporarily reflecting unsettled amounts. This conflict leads to incorrect calculations.

Bug Exploitation Scenario

  1. A user initiates a swap, causing temporary updates to the pool’s balance deltas to reflect the in-progress transaction.
  2. During the swap, the user calls the collectFees function to retrieve their portion of accrued fees.
  3. The collectFees function updates the balance delta, which is temporarily negative during the swap. This effectively credits the user’s owed fees against their outstanding balance.
  4. When the settle function is subsequently called to finalize the swap, the user’s adjusted balance delta results in:
  • Reduced payout: The user receives less than expected.
  • Transaction revert: If the delta remains incorrect, the transaction fails.

Implications

Although the financial impact is minimal, this bug degrades user experience by:

  • Reducing payouts.
  • Forcing users to retry transactions.

Why This Happens

The balance delta temporarily reflects unsettled values during swaps. Think of it as a ledger showing transactions in progress but not yet finalized. For example, if you're balancing your checkbook, the unsettled values would represent checks you've written but haven't cleared yet. Calling collectFees at this stage disrupts the system’s intermediate state.

Takeaway

To prevent such issues, users should avoid calling functions like collectFees during a swap, or the protocol should explicitly block such calls during this time. Ensuring correct operation sequencing is essential to avoid conflicts and maintain the system's integrity.


Conclusion

The findings presented in this article underscore essential lessons when developing secure and robust DeFi protocols. Despite being one of the most well-tested and mature protocols, the vulnerabilities discovered during repeated audits and formal verification demonstrate the importance of addressing edge cases, creating robust invariants through first-principles reasoning, and ensuring precise function execution in complex systems.

Uniswap's decision to engage various independent security teams highlights the need for diverse auditor perspectives in identifying vulnerabilities. This collaborative approach strengthens the protocol while also ensuring security and seamless user experiences across diverse blockchain environments.

Get every blog post delivered

Certora Logo
logologo
Terms of UsePrivacy Policy