#1 Cetus Incident: One Unchecked Shift Drains $223M in the Largest DeFi Hack of 2025

#1 Cetus Incident: One Unchecked Shift Drains $223M in the Largest DeFi Hack of 2025

On May 22, 2025, Cetus Protocol, which is the largest concentrated-liquidity DEX on Sui, suffered a major exploit that drained liquidity across multiple pools [1], resulting in an estimated ~$223 million in losses.

The exploit stemmed from a flaw in a custom overflow-prevention function (i.e., checked_shlw()) [2]. Due to an incorrect constant and comparison, the function failed to detect unsafe conditions before performing a left shift used in fixed-point u256 math. This allowed a silent truncation of the most significant bits during key delta calculations (e.g., the logic that computes how much token input is required for a given liquidity). By carefully selecting parameters (liquidity size and tick/price-range settings), the attacker could make the protocol compute the required deposit as essentially 1 unit of token, while still crediting the position with an enormous amount of liquidity. With that inflated position recorded on-chain, the attacker then removed liquidity and withdrew real reserves, draining the pools.

Background

Cetus uses a concentrated liquidity market maker (CLMM) design, where liquidity providers (LPs) supply liquidity only within a chosen price range (a tick interval). Instead of depositing funds uniformly across all prices, LPs concentrate capital between a lower and upper bound. This improves capital efficiency but makes the protocol heavily dependent on precise fixed-point math when converting between:

  • the liquidity amount credited to a position, and
  • the actual token amounts that must be paid in (or can be withdrawn out).

At a high level, when a user adds liquidity, the protocol computes the token deltas (how much underlying tokens are required) based on the current price and the chosen range. When a user removes liquidity, the protocol performs the inverse calculation to determine how much the position is entitled to withdraw.

If the “how much you must deposit” calculation can be made too small while the position is still credited with large liquidity, the attacker can later remove that credited liquidity and withdraw real reserves from the pool.

Vulnerability Analysis

The root cause was a bug in a helper function designed to safely perform a left-shift used in fixed-point u256 arithmetic (typically << 64 to apply a 2^64 scaling factor). In Move-based systems, overflow checks are not uniformly enforced across all operations, and bit shifting is one area where developers often add manual safeguards.

Cetus implemented an overflow-prevention helper (i.e., checked_shlw()) to determine whether shifting a u256 value left by 64 bits would exceed the 256-bit bound. However, due to an incorrect constant and comparison, the check could be bypassed for certain large inputs that should have been rejected.

Concretely, get_delta_a is used to compute the amount of underlying tokens (Token A) required to provide a given liquidity between two prices (sqrt_price_0 and sqrt_price_1). Inside get_delta_a, checked_shlw() is called to ensure the numerator used in the Token A calculation will not overflow when shifted.

However, the overflow check in checked_shlw() is wrong. It uses a mask of 0xffffffffffffffff << 192 (i.e., 2^256 - 2^192), which is far larger than the correct threshold. As a result, an input value that is greater than **2^192** but smaller than this mask can pass the check, even though shifting it left would exceed the u256 range. The shifted result is then truncated, producing an incorrect (smaller) value.

The figure below compares the vulnerable implementation and the patched one. The correct boundary should be 1 << 192, not 0xffffffffffffffff << 192. The attacker exploited this flawed check to mint an unusually large amount of LP tokens while depositing only 1 wei of Token A.

Attack Analysis

While the attacker applied the same technique across multiple pools, the underlying flow was consistent. Using this transaction as an example, the attack proceeded as follows.

1)Manipulate the pool price

The attacker used a flashloan to rapidly acquire 10,024,321.28 haSUI and then swapped out 5,765,124.79 SUI, driving the pool price down from 18,956,530,795,606,879,104 to 18,425,720,184,762,886. This price movement enabled the attacker to open a CLMM position that required only a minimal amount of one token, leveraging the “single-sided / nearly single-token” liquidity behavior in concentrated liquidity designs.

2) Add liquidity with an "almost free" deposit

Next, the attacker chose a very tight tick range (e.g., 300000–300200) and carefully tuned the target liquidity. In CLMM systems, token delta calculations depend on the square-root prices at the range boundaries, and narrow ranges can make certain intermediate values extremely sensitive.

By tuning these parameters, the attacker caused an internal multiplication to produce a u256 intermediate value that should have overflowed when left-shifted, but still passed the flawed checked-shift guard. As a result, after the unsafe shift-induced truncation, the protocol computed the required Token A amount as effectively 1 unit, while still minting/recording the position with massive liquidity (i.e., 10,365,647,984,364,446,732,462,244,378,333,008**)**.

3) Remove liquidity to extract real reserves

With an on-chain position that appeared to hold inflated liquidity, the attacker removed liquidity and withdrew assets as if the position had been properly funded. This is the step where the pool’s real reserves were drained.

4) Repeat across multiple pools

After validating the exploit primitive, the attacker replicated the same workflow across multiple pools, rapidly compounding the total losses.

Summary

The root cause was a faulty overflow check around a u256 left shift in the fixed-point math path, which allowed an overflowed shift to silently truncate high bits, which makes the required deposit appear near-zero while still crediting an LP position with massive liquidity, enabling reserve extraction.

Lessons

  • Be extra strict around shifts, scaling factors, rounding, and boundary conditions in fixed-point arithmetic.
  • Prefer proven safe-math primitives (or formalized invariants) over ad-hoc helpers; validate constants/thresholds carefully.
  • Add edge-case + property-based tests for max values, boundary ticks, and adversarial parameter combinations.

Reference

  1. Official Annoucement of Cetus Protocol

  2. Our short analysis


About BlockSec

BlockSec is a full-stack blockchain security and crypto compliance provider. We build products and services that help customers to perform code audit (including smart contracts, blockchain and wallets), intercept attacks in real time, analyze incidents, trace illicit funds, and meet AML/CFT obligations, across the full lifecycle of protocols and platforms.

BlockSec has published multiple blockchain security papers in prestigious conferences, reported several zero-day attacks of DeFi applications, blocked multiple hacks to rescue more than 20 million dollars, and secured billions of cryptocurrencies.

Sign up for the latest updates