Cetus Protocol Hack Analysis

On May 22, 2025, Cetus Protocol, a decentralized exchange (DEX) on the Sui and Aptos blockchains, was exploited due to a mathematical flaw in its liquidity calculation code. The attacker took advantage of this bug to generate fake LP tokens and used them to steal over $223 million in real assets, including SUI, USDC, and others.

HACKS & EXPLOITSINCIDENT ANALYSIS

Gracious Igwe

6/16/202514 min read

1. TL;DR of the Cetus Protocol Hack

  • On May 22, 2025, Cetus Protocol, a decentralized exchange (DEX) on the Sui and Aptos blockchains, suffered a major exploit. The hacker exploited a flaw in the system and stole over $223 million from user funds.

  • The attacker found a mathematical error in the code that calculates how much value a user should receive when providing liquidity. Using this bug, the hacker created fake tokens (LP tokens) and used them to drain real assets like SUI, USDC, and others.

  • A technical mistake in the way the protocol handles big number calculations allowed the hacker to push the system past its limits without being detected. Specifically:

    ⭢ The code didn't properly check when numbers were too big (called an overflow).

⭢ It trusted incorrect calculations due to a flawed safety check in a key math function.
⭢ This led to incorrect token minting, giving the hacker a way to cheat the system

  • $162 million was frozen by Sui validators to prevent further damage, however, over $61.5 million was moved to Ethereum and converted to 23,000 ETH and has not yet been frozen or retreived. The attack also caused the SUI token to drop 7%, and CETUS, the platform’s token, fell by 40%.

2. Full Report

On May 22, 2025, Cetus Protocol, a decentralized exchange (DEX) and concentrated liquidity protocol on the Sui and Aptos blockchains, suffered an exploit that led to the loss of over $223 million in user funds. The attacker drained significant assets from liquidity pools and bridged $61.5 million in USDC to Ethereum, where it was converted into approximately 23,000 ETH, worth around $62 million at the time. The root cause of the exploit was traced to an arithmetic overflow vulnerability in the protocol’s smart contract logic, which enabled the attacker to mint excessive LP tokens and systematically extract funds.

Cetus is the primary liquidity layer on the Sui blockchain, designed to offer efficient capital deployment via concentrated liquidity, similar to Uniswap v3. Liquidity providers can allocate funds within custom price ranges, and traders benefit from deeper pools and reduced slippage. The protocol is non-custodial and operates through smart contracts.

However, this efficiency relies on precise and secure mathematical operations. In this incident, the attacker exploited a flaw in the LP token minting logic, likely involving unchecked multiplication or rounding errors in the protocol’s math. By exploiting this vulnerability, they were able to mint LP tokens disproportionate to their input and drain assets across multiple pools, including SUI, USDC, and native tokens like TOILET—some of which fell by over 80% in the aftermath.

In response, Cetus quickly paused its smart contracts and launched an investigation. The attack had a huge effect on the Sui ecosystem, leading to a 7% drop in SUI price and a 40% drop in CETUS, the protocol’s native token.

Attack transactions

https://suivision.xyz/account/0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06?tab=Transaction+Blocks

https://etherscan.io/tx/0x787a0bc6305f26c9c6b78155f3271d4f3b8c321245881ee068a84dba04c8c2c0

Addresses

Sui: 0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06

Ethereum: 0x89012a55cD6b88e407C9d4ae9B3425F55924919b

0x0251536BfcF144B88e1aFa8fe60184Ffdb4cAF16

3. The core vulnerability

Cetus Protocol implements a concentrated liquidity market maker (CLMM) model, similar to Uniswap V3. In this model, liquidity providers (LPs) supply capital within user-defined price ranges, thereby improving capital efficiency and reducing slippage. This design enables LPs to concentrate liquidity in active trading ranges, maximizing their fee earnings relative to their capital outlay. However, this approach also imposes strict mathematical and precision requirements. Price movements, token swaps, and liquidity provisioning must be calculated with high accuracy, especially when they involve fractionalized values (like 0.0000001 tokens) and large-scale arithmetic operations.

To meet these requirements, Cetus relies on a robust external mathematical library called integer_mate, which includes modules for handling 256-bit unsigned integer arithmetic.

One of the key components of this library is the math_u256 module. This module facilitates various arithmetic operations, including multiplication, division, bit shifts, and overflow detection, using Move language constructs tailored for the Sui blockchain.

Among the functions defined in the module is checked_shlw, a utility function responsible for performing a left bitwise shift on a 256-bit unsigned integer while simultaneously checking for potential overflow. This is a crucial safety measure because shifting a large integer too far left can exceed the allowable 256-bit range, causing bits to be truncated — a dangerous arithmetic error.

💡Left-shifting is a common technique used to simulate multiplication by powers of 2, often employed to maintain precision in decimal or fixed-point arithmetic.

The checked_shlw function is designed to return two values:

  1. The result of the shift (if safe), and

  2. A boolean flag indicating whether an overflow occurred during the operation.

Here is a simplified description of how the function operates:

  • It takes an input n (a 256-bit unsigned integer).

  • It compares n against a predefined mask value.

  • If n is greater than this mask, the function assumes that shifting it left by 64 bits would overflow the 256-bit limit.

  • In that case, it returns (0, true) to indicate an unsafe operation.

  • Otherwise, it proceeds with the left shift n << 64 and returns the shifted result with an overflow flag of false.

The logic behind this seems sound and straightforward — to guard against overflows during left shifts. However, a deeper inspection reveals two critical flaws in this implementation that introduce serious vulnerabilities into the protocol’s logic.

The first major issue lies in how the function defines the mask, which serves as the upper boundary for determining whether a shift would cause overflow. In the current implementation, the mask is calculated as:

This expression shifts the maximum 64-bit unsigned integer (0xffffffffffffffff, or 2^64 - 1) to occupy the top 64 bits of the 256-bit space. Mathematically, this yields:

This is equivalent to 2^192, which is:

May 23, 2025 With no response from the attacker, Cetus (with backing from Sui Foundation) announced a $5 million bounty for information leading to the hacker’s identification and arrest.

At first glance, this appears reasonable, as it seems to reserve the upper 64 bits as a safety buffer. However, the logic behind it is flawed.

To understand why, let’s consider the purpose of the mask: it is meant to determine the maximum allowable value for n such that n << 64 remains within the 256-bit boundary. That is, if the shifted result exceeds 2^256 - 1, it would overflow and become invalid.

To avoid overflow, the most significant bit (MSB) of n must be located no higher than bit position 191 (i.e., n < 2^192). This is because shifting a number by 64 bits moves each bit 64 positions to the left. If a 1-bit is located at position 192 or above, the shift will push it beyond the 255th bit — the maximum representable index in a 256-bit number.

Therefore, the correct mask should be:

Any value equal to or exceeding this threshold will definitely overflow when shifted by 64 bits. The currently implemented mask, however, permits values up to 2^256 - 2^192, which is approximately (2^64 - 1) times larger than the safe upper bound. This means that many unsafe values are mistakenly treated as valid, allowing silent overflows to occur.

The second flaw concerns the logic used to compare n against the mask. The current implementation checks:

This condition detects only those values of n that are strictly greater than the mask. However, it fails to account for the boundary case where n == mask. This is problematic because shifting mask itself left by 64 bits produces a result that occupies the full 256-bit space and thus overflows.

This off-by-one error allows a dangerous value to pass the check. When n == mask, the function incorrectly deems the operation safe and proceeds with the left shift, producing a 320-bit intermediate result. Since the system only supports 256-bit numbers, the high 64 bits of this result are discarded, leading to an incorrect value.

4. Combined Impact of the Flaws

These two flaws combine to form a critical vulnerability. Unsafe values that should be rejected are allowed to proceed, resulting in silent arithmetic overflows. This issue is particularly severe given how the checked_shlw function is used in the protocol’s internal price and liquidity calculations.

One such use case occurs in the get_delta_a function, which computes the change in token A (delta_a) during a price shift.

Here, sqrt_price_diff represents the magnitude of price movement in square root form, while liquidity is the user-supplied liquidity value.

The function first calculates the absolute difference between sqrt_price_0 and sqrt_price_1. This difference is important because it defines how much the price has moved during the trade. If there is no movement in price (sqrt_price_diff == 0) or if the liquidity is zero, the function returns zero early, since no amount of token A would need to be adjusted.

Next, these two values (sqrt_price_diff & liquidity) are multiplied using a 256-bit multiplication function (full_mul) to retain precision. This multiplication is necessary to retain precision, especially for very small price changes or high liquidity values.

The resulting product is then shifted left by 64 bits using checked_shlw to scale it into a fixed-point format. This is a common technique in fixed-point arithmetic to handle precision.

At this stage, a vulnerability is introduced. If the product of liquidity * sqrt_price_diff is greater than or equal to 2^192, the shift operation will overflow the 256-bit boundary. However, due to flaws in the checked_shlw implementation — a faulty overflow mask and an incorrect comparison operator —, such dangerously large values are allowed to pass through without triggering an abort. The shift proceeds, and the most significant 64 bits of the result are silently discarded, resulting in an incorrect and much smaller number.

This faulty result is then used in subsequent calculations to determine the amount of token A required or released. Since the computation has lost significant bits, the final value is drastically altered, often appearing smaller than it should be.

5. Exploit Scenario

Let’s consider an example:

  • An attacker initiates a swap or liquidity addition with an extremely high liquidity value.

  • They pair this with a sqrt_price_diff value derived from a dramatic price swing (e.g., via a flash loan).

  • The product liquidity * sqrt_price_diff results in a number slightly below 2^256 - 2^192, large enough to overflow when shifted, but still allowed by the faulty mask.

  • The checked_shlw function shifts the product left by 64 bits, causing an overflow.

  • The overflow truncates significant bits, resulting in a small or malformed value.

  • The protocol uses this truncated value to compute token balances, believing that a valid large liquidity amount was provided.

  • The attacker receives an excessive amount of token A in return, extracting funds without providing commensurate input.

This attack took advantage of both the mathematical oversight and the unchecked edge case to extract funds from the protocol in a way that appears legitimate on-chain.

6. Attack Flow

The first step involved the attacker taking a large flash loan of 10,024,321.28 haSUI. The attacker used the flash loan to manipulate the price within a concentrated liquidity pool. When the attacker introduced the borrowed tokens into the pool, it caused a dramatic drop in the token price. By forcing the pool price to a low level, the attacker altered the behavior of the pool’s liquidity curves and created favorable conditions for the next steps in the attack.

The attacker repeated this pattern roughly 280+ times, suggesting that they had likely automated the process and were testing multiple combinations of price points, tick ranges, and liquidity settings to find optimal outcomes.

With the pool’s price severely distorted, the attacker created a narrow-range tick liquidity position between ticks 300,000 and 300,200. Concentrated liquidity protocols use tick ranges to define the price boundaries where liquidity is active. When these ranges are tight and the curve is steep, even small mathematical inaccuracies in liquidity math can have large effects on LP token distribution. This was critical to the next stage of the exploit.

With the narrow tick range established and the curve now steep, the attacker proceeds to exploit a vulnerability in the liquidity math logic. It involved adding a very small amount of liquidity, as little as 1 token.

Despite this tiny input, the system mistakenly credited the attacker with a massive amount of LP tokens. This was caused by a flaw in the way liquidity was calculated. Specifically, the function used to shift and multiply values (checked_shlw) failed to handle certain inputs correctly.

It only checked if a number was above a set threshold before shifting it left by 64 bits. However, values below this threshold could still trigger an internal overflow during the shift, which wasn’t detected. As a result, the system severely underestimated the amount of tokens required and minted a full LP share to the attacker based on faulty math. This allowed the attacker to drain a large portion of the pool while only supplying a minimal amount of tokens.

Once in possession of the LP tokens, the attacker began removing liquidity in phases. This phased withdrawal was designed to look less suspicious. First, they removed 10,024,321.28 haSUI, then 1 haSUI, and finally another 10,024,321.28 haSUI. This approach helped bypass any naive detection methods that might flag large, sudden liquidity removals.

Finally, the attacker repaid the flash loan—a total of 20,048,642.56 haSUI—and retained the rest as profit. Thanks to the exploit, they walked away with approximately 10 million haSUI and 5.76 million SUI. All of this was achieved with just 1 token as capital, and the temporary flash loan was fully repaid within the same transaction.

7. Impact of the attack

Asset losses: About $223 million in total liquidity was affected, with $162 million frozen by Sui validators to prevent further damage. $61.5 million is still lost, including:

  • 12.9 million SUI (worth ~$54M at the time)

  • $60M in USDC

  • $4.9M in Haedal Staked SUI

  • $19.5M in TOILET

Market Impact: Tokens paired with SUI saw their prices crash by 70–80%, reflecting both the liquidity loss and market panic.

8. How the Protocol Responded

May 22, 2025 Cetus announced the detection of an incident and paused the smart contract to prevent further losses. An investigation was initiated. The team confirmed that an attacker stole around $223 million in total. Out of this, $162 million was successfully frozen. The protocol began working with the Sui Foundation and other partners to trace funds and explore recovery options.

Thereafter, they provided more detail:

  • Engaged the Sui Foundation and third parties for forensic analysis and tracing.

  • Identified and fixed the root cause to prevent similar issues across the ecosystem.

  • Brought in anti-cybercrime experts for fund recovery efforts and negotiations.

  • Reached out to the hacker’s Ethereum address with a whitehat settlement offer and a promise to drop legal action if funds were returned.

They proposed an on-chain community vote to unlock and return the frozen $162M to affected users. The team stated that this decision would require support from validators and stakers, not unilateral action.

At May 25, 2025 a Q&A was published to address community concerns and provide transparency around recovery progress and the roadmap ahead.

May 26, 2025 Cetus released a full incident report, explaining the exploit, root cause, response steps, and next actions.

May 27, 2025 Cetus revealed that, with support from the Sui Foundation and using its own treasury, it could fully compensate affected users — if the community vote to unlock frozen funds passed. They committed to beginning recovery regardless of the outcome and expressed regret for the incident’s impact.

May 31, 2025 Following a successful on-chain vote, the frozen funds were moved to a multisig wallet controlled by Cetus, the Sui Foundation, and OtterSec. The team confirmed it was moving into the recovery phase, focused on contract upgrades, restoring liquidity, and relaunching operations.

Cetus Protocol responded swiftly to the exploit by pausing smart contracts, freezing funds, collaborating with security partners and law enforcement, and engaging the community. A clear recovery roadmap was laid out, including a bounty program, whitehat settlement offer, on-chain governance, and eventual asset recovery plans, all aimed at making users whole and restoring trust.

They also promptly fixed the error in the checked_shlw function of the inter_mate library via GitHub commits :

Fix 1:

Changed mask from 0xffffffffffffffff << 192 to 1 << 192

Fix 2:

Changed condition from n > mask to n >= mask

The original condition if (n > mask) { ... } would only reject values strictly greater than the mask.

The new condition if (n >= mask) { ... } now also rejects values equal to ****the threshold — in this case, 2^192, potentially blocking any value that could result in a 256-bit overflow.

9. How the attack could have been prevented

  1. Use Safe Encoding Libraries: Use well-audited libraries like OpenZeppelin’s SafeCast or create robust internal versions. Avoid manually shifting and masking bits unless necessary and thoroughly tested.

  2. Unit Tests for Edge Cases: Write unit tests for edge cases like:

    ⭢ Maximum possible valid values (e.g., 2^192 - 1)

    ⭢ Boundary overflows (e.g., 2^192)

  3. Auditing All Assumptions in Math Functions: The exploit stemmed from the assumption that inputs would always be within bounds. A code audit should question these assumptions, especially for low-level bit manipulations.

  4. Bug Bounty and Continuous Audits: Regular security reviews and public bounties can expose these edge cases before attackers do.

10. Conclusion

The Cetus Protocol exploit highlights the importance of rigorous mathematical precision in smart contract design, particularly when implementing complex financial primitives like concentrated liquidity. A seemingly minor miscalculation in overflow protection logic led to the silent failure of key safeguards, allowing an attacker to mint excess LP tokens and extract millions in user funds. This breach not only devastated the Cetus ecosystem but also shook confidence in the Sui blockchain.

At Chainvestigate, we provide expert blockchain forensics, deep protocol analysis, and fund tracing solutions that help teams stay ahead of adversaries.

Stay secure. Stay vigilant. Let Chainvestigate guide your response and recovery.

The original line let mask = 0xffffffffffffffff << 192; calculates a bitmask that sets the highest 64 bits of a 256-bit number. This effectively results in mask = 0xffffffffffffffff000000000000000000000000000000000000000000000000 which has the top 64 bits set to 1, and the rest as 0. This is not the correct way to check if a value exceeds the 192-bit range.

The new line let mask = 1 << 192; creates a value that is 2^192, which represents the smallest number that would overflow a 192-bit unsigned integer. This ensures that only values less than 2^192 are considered safe for a 64-bit left shift.