SlowMist: Analysis of the $230 Million Cetus Hack
Authors: Victory & Lisa
Editor: Liz
Background
On May 22, community users noticed that Cetus, a DEX in the SUI ecosystem, appeared to have been attacked. The liquidity pool depth dropped sharply, and prices of multiple token pairs on Cetus plummeted. The total loss was estimated to exceed $230 million. Subsequently, Cetus issued an announcement.
The SlowMist Security Team immediately launched an analysis and issued a security alert. The following is a detailed explanation of the attack and fund flow.
Key Information
- One of the attack transactions:
https://suiscan.xyz/mainnet/tx/DVMG3B2kocLEnVMDuQzTYRgjwuuFSfciawPvXXheB3x - Attacker address:
0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06 - Target pool address:
0x871d8a227114f375170f149f7e9d45be822dd003eba225e83c05ac80828596bc - Token pair involved:
haSUI / SUI
Attack Analysis
The core of this attack is a sophisticated overflow bypass, where the attacker used a very small amount of tokens to swap for a large amount of liquidity. The specific steps are as follows:
1. Flash Loan Crashes Price
The attacker first took out a flash loan of 10,024,321.28 haSUI, causing the pool price to plummet from 18,956,530,795,606,879,104 to 18,425,720,184,762,886, a 99.90% drop.
2. Create Narrow Range Liquidity Position
The attacker created a liquidity position with a very narrow price range:
- Lower Tick: 300000 (price: 60,257,519,765,924,248,467,716,150)
- Upper Tick: 300200 (price: 60,863,087,478,126,617,965,993,239)
- Width: only 1.00496621%
3. Overflow in checked_shlw
This is the core of the vulnerability. The attacker claimed to add: 10,365,647,984,364,446,732,462,244,378,333,008 liquidity.
But only 1 Token A was actually charged.
Let’s analyze how the attacker was able to obtain a massive amount of liquidity with just 1 token. The core issue lies in an overflow check bypass vulnerability within the get_delta_a
function, specifically in the checked_shlw
operation. The attacker exploited this flaw, causing a serious miscalculation in the amount of haSUI required to add the intended liquidity. Since the overflow went undetected, the system significantly underestimated the required haSUI, allowing the attacker to use a tiny amount of tokens in exchange for a huge amount of liquidity, thereby completing the attack.
When the system calculates how much haSUI is required to add such a large amount of liquidity:
public fun get_delta_a(
sqrt_price_0: u128,
sqrt_price_1: u128,
liquidity: u128,
round_up: bool
): u64 {
let sqrt_price_diff = if (sqrt_price_0 > sqrt_price_1) {
sqrt_price_0 - sqrt_price_1
} else {
sqrt_price_1 - sqrt_price_0
};
if (sqrt_price_diff == 0 || liquidity == 0) {
return 0
};
let (numberator, overflowing) = math_u256::checked_shlw(
full_math_u128::full_mul(liquidity, sqrt_price_diff)
);
if (overflowing) {
abort EMULTIPLICATION_OVERFLOW
};
let denominator = full_math_u128::full_mul(sqrt_price_0, sqrt_price_1);
let quotient = math_u256::div_round(numberator, denominator, round_up);
(quotient as u64)
}
The key issue lies in the flawed implementation of the checked_shlw
function. In fact, any input value smaller than 0xffffffffffffffff << 192
can bypass the overflow check. However, when such values are left-shifted by 64 bits, the result exceeds the range of the u256
data type. As a consequence, the higher-order bits are truncated, and the final result becomes significantly smaller than expected. This leads the system to underestimate the required amount of haSUI in subsequent calculations.
public fun checked_shlw(n: u256): (u256, bool) {
let mask = 0xffffffffffffffff << 192; // ❌ Incorrect mask
if (n > mask) { // ❌ Incorrect condition
(0, true)
} else {
((n << 64), false) //⚠️ n shifted left by 64 bits overflows. When converted back to u256, high bits are truncated, actual value becomes smaller.
}
}
- Incorrect mask:
0xffffffffffffffff << 192
= an extremely large value (approximately 2^256 - 2^192) - Almost all input values are smaller than this mask, so they bypass the overflow check.
- The real problem: when
n >= 2^192
thenn << 64
exceeds theu256
range and gets truncated.
The attacker constructed the multiplication result: liquidity * sqrt_price_diff = 6277101735386680763835789423207666908085499738337898853712
· Less than the incorrect mask, bypassing the overflow check,
· but after shifting left by 64 bits, the value exceeds the maximum of u256
, causing the overflowing part to be truncated.
· This results in the final computed value being approximately less than 1, but since it is rounded up, the quotient
ends up being calculated as 1.
let quotient = math_u256::div_round(numberator, denominator, round_up);
(quotient as u64) // Here, the numerator is smaller than the denominator, which causes the result to equal 1.
4. Remove Liquidity for Profit
The attacker then removed liquidity in three steps:
- 10,024,321.28 haSUI
- 1 haSUI
- 10,024,321.28 haSUI
5. Repay Flash Loan and Profit
After repaying the flash loan, the attacker netted:
- About 10,024,321.28 haSUI
- About 5,765,124.79 SUI
Protocol Fix
After the attack, Cetus released a patch: https://github.com/CetusProtocol/integer-mate/pull/7/files#diff-c04eb6ebebbabb80342cd953bc63925e1c1cdc7ae1fb572f4aad240288a69409
Fixed code:
public fun checked_shlw(n: u256): (u256, bool) {
let mask = 1 << 192; // ✅ Corrected threshold: 2^192
if (n >= mask) { // ✅ Corrected condition to properly detect overflow
(0, true)
} else {
((n << 64), false)
}
}
Explanation:
- Changed mask from 0xffffffffffffffff << 192 to 1 << 192
- Changed condition from
n > mask
ton >= mask
- Now properly detects overflows in left-shift operations
MistTrack On-Chain Tracing
MistTrack found that the attacker(0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06) gained about $230 million worth of assets (SUI, vSUI, USDC, etc.).
We found that the attacker prepared the Gas Fee two days in advance and made an attempt before the actual attack, but it failed:
After the attack, the funds were bridged via Sui Bridge, Circle, Wormhole, and Mayan to an EVM address: 0x89012a55cd6b88e407c9d4ae9b3425f55924919b.
5.2341 WBNB was sent to the above BSC address (0x89012a55cd6b88e407c9d4ae9b3425f55924919b):
About $10M worth of tokens were deposited to Suilend:
24,022,896 SUI was transferred to: 0xcd8962dad278d8b50fa0f9eb0186bfa4cbdecc6d59377214c88d0286a0ac9562
(Not moved yet).
Fortunately, with the joint efforts of the SUI Foundation and ecosystem projects, $162 million of assets on SUI have been frozen.
Next, we used the on-chain anti-money laundering and tracking tool MistTrack to analyze the address 0x89012a55cd6b88e407c9d4ae9b3425f55924919b on EVM, which received cross-chain funds.
This address received 5.2319 BNB on BSC and has not transferred out yet:
On Ethereum, this address received 3,000 USDT, 40.88 million USDC, 1,771 SOL, and 8,130.4 ETH.
Among them, USDT, USDC, and SOL were swapped into ETH through CoW Swap, ParaSwap, and others:
Then, this address transferred 20,000 ETH to the address 0x0251536bfcf144b88e1afa8fe60184ffdb4caf16, which has not transferred out yet:
Currently, the balance of this address on Ethereum is 3,244 ETH:
MistTrack has added the above related addresses to its malicious address database, and we will continue to monitor the balances of these addresses.
Summary
This attack demonstrated the power of a mathematical overflow vulnerability. The attacker precisely selected parameters and exploited the flaw in the checked_shlw function to obtain liquidity worth billions at the cost of only 1 token. This was an extremely sophisticated mathematical attack. The SlowMist security team recommends that developers strictly validate the boundary conditions of all mathematical functions in smart contract development.
About SlowMist
SlowMist is a blockchain security firm established in January 2018. The firm was started by a team with over ten years of network security experience to become a global force. Our goal is to make the blockchain ecosystem as secure as possible for everyone. We are now a renowned international blockchain security firm that has worked on various well-known projects such as HashKey Exchange, OSL, MEEX, BGE, BTCBOX, Bitget, BHEX.SG, OKX, Binance, HTX, Amber Group, Crypto.com, etc.
SlowMist offers a variety of services that include but are not limited to security audits, threat information, defense deployment, security consultants, and other security-related services. We also offer AML (Anti-money laundering) software, MistEye (Security Monitoring) , SlowMist Hacked (Crypto hack archives), FireWall.x (Smart contract firewall) and other SaaS products. We have partnerships with domestic and international firms such as Akamai, BitDefender, RC², TianJi Partners, IPIP, etc. Our extensive work in cryptocurrency crime investigations has been cited by international organizations and government bodies, including the United Nations Security Council and the United Nations Office on Drugs and Crime.
By delivering a comprehensive security solution customized to individual projects, we can identify risks and prevent them from occurring. Our team was able to find and publish several high-risk blockchain security flaws. By doing so, we could spread awareness and raise the security standards in the blockchain ecosystem.