Skip to content

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?

Subject Value
Attacker wallet 0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06
First exploit transaction DVMG3B2kocLEnVMDuQzTYRgjwuuFSfciawPvXXheB3x
haSUI/SUI pool 0x871d8a227114f375170f149f7e9d45be822dd003eba225e83c05ac80828596bc

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”

analyze_attack_tx:

{ "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.

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.

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.

find_funding_source:

{ "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.

  • 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_module and the fix with diff_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.