Protocol exploit: Cetus CLMM
Question: what did the wallet behind the 22 May 2025 Cetus CLMM exploit take, from which pools, and where did the proceeds leave Sui?
Sources
Section titled “Sources”- Cetus, incident report
- Dedaub, the Cetus AMM $200M hack
- Case file:
cetus-2025-05.json
| Subject | Value |
|---|---|
| Attacker wallet | 0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06 |
| First exploit transaction | DVMG3B2kocLEnVMDuQzTYRgjwuuFSfciawPvXXheB3x |
| haSUI/SUI pool | 0x871d8a227114f375170f149f7e9d45be822dd003eba225e83c05ac80828596bc |
1. Find the first exploit transaction
Section titled “1. Find the first exploit transaction”get_transaction_history
with the oldest transactions first:
{ "address": "0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06", "order": "oldest", "limit": 5 }"transactions": [ { "digest": "EKHNUkpyzuzBg85rFXxpvXiR4kYU9quRXDCZNUmqYnuh", "timestamp": "2025-05-19T15:13:56.159Z", …, "status": "success", …, "subject_flow": [ { …, "formatted": "9.98065224 SUI", … } ] }, { "digest": "BTMCNZd2kt6b1ALvntNC99GGo1nancJtJHAbxi5SnCpR", "timestamp": "2025-05-22T07:26:03.159Z", …, "status": "failure", … }, { "digest": "DVMG3B2kocLEnVMDuQzTYRgjwuuFSfciawPvXXheB3x", "timestamp": "2025-05-22T10:30:50.476Z", …, "status": "success", …, "subject_flow": [ { …, "formatted": "5765124.463062928 SUI", … }, { …, "formatted": "10024321.275017081 haSUI", … } ] }, …]The wallet received SUI once, failed one transaction at 07:26, and first
succeeded at 10:30:50 UTC. Cetus’s incident report dates the exploit from
10:30:50, and Dedaub cites DVMG3B2k as an attack transaction.
2. Break down the first exploit transaction
Section titled “2. Break down the first exploit transaction”{ "digest": "DVMG3B2kocLEnVMDuQzTYRgjwuuFSfciawPvXXheB3x" }"profit": { "address": "0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06", "gains": [ { …, "symbol": "haSUI", …, "amount": "10024321275017081", … }, { …, "symbol": "SUI", …, "amount": "5765124463062928", … } ], …},"swaps": [ { …, "pool": "0x871d8a227114f375170f149f7e9d45be822dd003eba225e83c05ac80828596bc", …, "price_change_pct": -99.999906, … }],"anomalies": [ { "severity": "high", "code": "outsized-mint", … }, { "severity": "high", "code": "shared-state-jump", … }, … { "severity": "info", "code": "flashloan-pattern", … }]The transaction took a flash swap on the haSUI/SUI pool, dropped the pool’s
price by 99.9999%, and left the attacker 10,024,321.28 haSUI and 5,765,124.46
SUI. outsized-mint means a position was credited more liquidity than the
amounts paid for it can buy. Dedaub traces this to a flawed overflow check in
the liquidity math.
3. Total the whole run
Section titled “3. Total the whole run”summarize_incident_losses
over every transaction the attacker sent in the exploit window:
{ "sender": "0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06", "start": "2025-05-22T10:30:00Z", "end": "2025-05-22T10:46:00Z", "max_groups": 15 }"transactions_read": 287,"priced_coins": [ { …, "symbol": "USDC", …, "attacker_net": 55429398.24745, … }, { …, "symbol": "SUI", …, "attacker_net": 12989333.115670312, … }, { …, "symbol": "haSUI", …, "attacker_net": 10138247.832730472, … }, …],"failed_transactions": [ "6rHDib8ddeGTeQVGXRGJEjWBoG4Gd62ntgkWwnFXieGU", … ],"groups": [ { "pools": [ "0x871d8a227114f375170f149f7e9d45be822dd003eba225e83c05ac80828596bc" ], …, "transactions": [ "DVMG3B2kocLEnVMDuQzTYRgjwuuFSfciawPvXXheB3x" ], … }, …]The attacker sent 287 transactions between 10:30:50 and 10:45:38 UTC, 22 of
which failed. Per-coin amounts are read from balance changes. Coins are priced
near their transaction times; usd_basis reports the method and coverage.
When coin legs or objects cannot be priced, totals.partial is true and
unpriced_remainder lists the unpriced coins. Missing debits can raise the
net, so partial totals are not lower bounds.
4. Find where the proceeds left Sui
Section titled “4. Find where the proceeds left Sui”summarize_address_flows
from the end of the exploit to the end of the day:
{ "address": "0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06", "from": "2025-05-22T10:46:00Z", "to": "2025-05-23T00:00:00Z" }"coverage": { …, "complete": true, … },"coins": [ { …, "symbol": "USDC", …, "in": 5885703.591291, "out": 61315101.836523, "net": -55429398.245232, … }, { …, "symbol": "SUI", …, "in": 11033566.975673009, "out": 24022900.75773294, "net": -12989333.782059932, … }, { …, "symbol": "haSUI", …, "in": 0.008952314, "out": 10138247.841682788, "net": -10138247.832730472, … }, { …, "symbol": "USDT", …, "in": 0, "out": 19013239.615614, "net": -19013239.615614, … }, …],"top_recipients": [ { "address": "0xcd8962dad278d8b50fa0f9eb0186bfa4cbdecc6d59377214c88d0286a0ac9562", "coins": [ { "symbol": "SUI", "amount": 24022895.1732351, … } ], … }, …],"bridge_exits": { "transaction_count": 76, "by_bridge": [ { "bridge": "Wormhole", "transactions": 4, … "destinations": [ { …, "account": "eip155:1:0x89012a55cd6b88e407c9d4ae9b3425f55924919b", … }, { …, "account": "eip155:56:0x89012a55cd6b88e407c9d4ae9b3425f55924919b", … } ] }, { "bridge": "Circle CCTP", "transactions": 7, "sent": [ { "symbol": "USDC", "amount": 6885703.589073, … } ], … }, { "bridge": "Mayan MCTP", "transactions": 55, "sent": [ { "symbol": "USDC", "amount": 54429398.24745, … } ], … }, { "bridge": "Sui Bridge", "transactions": 10, … } ]}All 76 bridge exits name 0x89012a55 as the recipient, the Ethereum address
the Cetus report gives. The largest Sui recipient, 0xcd8962da, received
24,022,895.17 SUI; the Cetus report names it as a second attacker wallet.
complete: true means every transaction in the window was read.
The wallet sent out more SUI and USDC than step 3 says it took because it
swapped other coins into them first. The digests in unattributed_inflows and
unattributed_outflows show haSUI and vSUI swapped for SUI and USDT swapped
for USDC; it also sent out USDY, FDUSD, afSUI, ETH and smaller amounts. In
this window it received 11,033,566.98 SUI and 5,885,703.59 USDC, and its net
is 12,989,333.78 SUI and 55,429,398.25 USDC out. That net matches the
12,989,333.12 SUI and 55,429,398.25 USDC step 3 totals for the exploit, to
within one SUI. The USDC sent over Circle CCTP and Mayan MCTP,
61,315,101.84 in all, is the exploit’s USDC plus the USDC from the swaps.
5. Check who funded the wallet
Section titled “5. Check who funded the wallet”{ "address": "0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06" }"chain": [ { …, "funded_by": "0xff1070d40277a3d748a3222b44eab08ed588b256094ecdc2090badf0f9f5e9f4", "funding_tx": "EKHNUkpyzuzBg85rFXxpvXiR4kYU9quRXDCZNUmqYnuh", "timestamp": "2025-05-19T15:13:56.159Z", "amount": "9.98065224 SUI", … }],"origin_popularity": { "popular": true, … },"stop_reason": "reached a high-fanout distributor … ancestry beyond it carries no attribution"The funder pays many unrelated addresses, so the walk stops there. Neither Cetus nor Dedaub names a funder.
What this shows and what it does not
Section titled “What this shows and what it does not”- The amounts, digests, timestamps and bridge recipients are read from the chain and do not depend on a third party.
- Coin USD figures use historical quotes near each transaction; objects use their transaction times. Partial pricing can leave out credits or debits.
- The anomaly flags point at the mechanism but do not prove it. The case file
confirms it by reading the pool’s bytecode with
disassemble_moduleand the fix withdiff_package_upgrade; the Typus example shows that method. - The funder is a high-fanout wallet. Being funded by it is not a link to its other recipients.
- Bridge exits end the Sui side of the trace. What happened on Ethereum is not read.
Related
Section titled “Related”- Fund flows: tracing, first-in-first-out allocation and path finding.
- Reading a transaction: failed transactions and objects that are not coins.
- Truncated lists: the
truncatedandomittedfields these answers carry.