conrad zeus
628 posts


If you just woke up and saw $DOT @Polkadot hacked, here is what I found (long-read)
THE SETUP
Hyperbridge uses ISMP (Interoperability State Machine Protocol) to bridge Polkadot assets to Ethereum. The architecture:
- EthereumHost - stores consensus state & commitments
- HandlerV1 - verifies proofs, dispatches messages
- Consensus Client - verifies BEEFY/GRANDPA proofs from Polkadot
- TokenGateway - mints/burns wrapped assets (DOT, ARGN, MANTA, etc.)
Two critical facts about the live config:
1) challengePeriod = 0 (no delay before state commitments become usable)
2) The consensus client (0xA0Ad0CfD02509321AA5968cD04A8E205Ce53669a) is UNVERIFIED - no public source code
---
THE ATTACK (one atomic transaction)
TX: etherscan.io/tx/0x240aeb9a8…
Attacker 0xC513E4f5D7a93A1Dd5B7C4D9f6cC2F52d2F1F8E7 deployed an exploit contract whose constructor executed this entire sequence:
1. Deploy sub-contract (0x31a165a956842aB783098641dB25C7a9067ca9AB)
2. Call run() on sub-contract
3. Sub-contract calls HandlerV1.handleConsensus() with a FORGED Polkadot consensus proof
4. The unverified consensus client accepts the forged proof
5. A malicious state commitment (containing attacker-controlled MMR root) gets stored in EthereumHost
6. Since challengePeriod = 0, the commitment is IMMEDIATELY usable, no fisherman dispute window
7. Sub-contract calls HandlerV1.handlePostRequests() with a crafted MMR proof referencing the just-stored malicious root
8. The MMR verification passes trivially, attacker controls BOTH the root and the proof
9. The forged ISMP message contains: action=ChangeAssetAdmin, source="POLKADOT-3367", newAdmin=sub-contract
10. TokenGateway checks request.source == "POLKADOT-3367" - PASSES (source was embedded in forged MMR leaf)
11. TokenGateway calls DOT.changeAdmin(sub-contract), sub-contract is now DOT admin
12. Sub-contract calls DOT.mint(1,000,000,000 DOT)
13. Sub-contract approves DEX router for max, swaps 1B DOT for 108.2 ETH via Uniswap V4
14. ETH flows back: sub-contract -> exploit contract -> attacker EOA
All in one transaction. Gas cost: 0.000339 ETH. Profit: 108.2 ETH.
---
WHY THE SOURCE CHECK FAILS
TokenGateway's authorization for privileged actions like ChangeAssetAdmin:
if (!request.source.equals(host.hyperbridge())) revert UnauthorizedAction();
This byte comparison is not a security boundary. It relies entirely on the integrity of the consensus proof upstream. The source field lives inside the MMR leaf, when the attacker controls the MMR root, they control every leaf, including the source field. The check becomes a tautology.
---
ROOT CAUSE
Two combined weaknesses:
challengePeriod = 0: The challenge period is the only defense against forged consensus proofs. When it's zero, any fraudulent state commitment accepted by the consensus client is immediately exploitable in the same block. No fisherman window. No dispute mechanism. Plant and exploit in one tx.
Unverified consensus client: The contract at 0xA0Ad0CfD02509321AA5968cD04A8E205Ce53669a has no public source code. Its verifyConsensus() accepted a forged BEEFY proof. Either a cryptographic bug, a deliberately weakened replacement, or a compromised signing key.
---
SCOPE: NOT JUST DOT
The attacker exploited multiple Hyperbridge-wrapped assets via the same vector:
- DOT: 1B minted (~$1.78B face value)
- ARGN (Argon): ~999B minted (~$1.03B face)
- MANTA: 211K minted (partially captured by MEV bot)
- CERE: ~23B minted (partially captured by MEV bot)
All ERC6160Ext20 tokens managed by the same TokenGateway. Same forged ISMP message, different action payloads.
---
ATTACKER PROFILE
- 33-day-old wallet, seeded from a RAILGUN RelayAdapt contract (not a simple EOA)
- Spent a month deploying 15+ test contracts against live state
- Used LI.FI/GasZip to bridge ETH across chains immediately after funding (obfuscation)
- Pre-deployed custom zk-SNARK verification keys via RAILGUN 8.5 months before the exploit
- Laundering confirmed via RAILGUN zk shielded pool, withdrawing in 15 ETH denominations to fresh exit wallets
Months of preparation.
---
FUND FLOW
Primary swap: ~108.2 ETH ($237k)
Secondary waves: ~4,924 ETH ($10.8k)
Later stablecoin: ~$8k (WETH/USDC/USDT)
Total extracted: ~$250kM+
EthereumHost is frozen (status=All). Attacker is laundering through RAILGUN. No bridge-out transactions observed yet. Exit wallet 0x43C291c59164e55E27326a719c4FD05a1b72F8b2 holds ~105 ETH from RAILGUN withdrawals.
---
KEY ADDRESSES
Attacker: etherscan.io/address/0xC513…
DOT Token: etherscan.io/address/0x8d01…
TokenGateway: etherscan.io/address/0xFd41…
EthereumHost: etherscan.io/address/0x792A…
Consensus Client (unverified): etherscan.io/address/0xA0Ad…
RAILGUN Exit Wallet: etherscan.io/address/0x43C2…
English

@yazcal s t o p s h o w c a s i n g m a r i n y o u a r e g o i n g t o g e t m e p r i c e d o u t
English


do people actually think Github commits are a signal?
why not just use the product?
goodalexander@goodalexander
lately I've been buying projects where the founder hasn't quit, the github is active and the token is down 90%+ surprisingly common I actually think relatively disgusting amounts of money to be made before the inevitable collapse in 2028
English

@Rangbazz_ nothing's dead. your attention span is.
the game didn't stop, you just stopped watching the right plays
English

Airdrop dead
GameFi dead
Metaverse dead
Memecoin dead
NFT dead
InfoFI dead
ICO dead
Web3 dead
Defi dead
Perpdex dead
Altcoin dead
Testnet dead
So what solution for we survive in 2026? @aixbt_agent
English

どんな曲なんやろって単純に16分詰めて復元してみたけど、原曲こんな感じかな?
でもこれステムごとに音変えながら16分足して成立させてる気がする。発想もセンスもえぐい
Hizuru Saito@M3-2026春サ-26a@Hizuru_Saito
Sunoで生成した16ビートのIDMを、一拍ごとに16分音符ひとつ分つぎ足してクインテプレット・ビート(Quintaplet Beat、5連符ビート)にしてみました。16ビートとは一味違う不思議なグルーヴを感じていただければ幸いです😉 音楽:Suno, Cubase 画像:Midjourney 動画:Grok Imagine
日本語

@ShimazuSystems also would be amazing if you could load instruments here from the sample view

English

@ShimazuSystems :OOOO
need to be able to assign an instance of an instrument to multiple slots here!!

English

@ShimazuSystems Ah! That also explains the pitch bend issue. I dealt w this while building an audio plugin a while back.. think i used an loscil osc that acted as a source of truth, but that was c …
English

@conrad___zeus That's the one I went through! Yeah its 48, the engine is designed this way because its standalone, the imports were supposed to be a third order priority feature but I really worked through it 😅
English

@ShimazuSystems ah i see. if your engine is sampling at 48 the master pitch issue would make sense.
assume you saw this : github.com/jthlim/impulse…

English

@conrad___zeus Impulse itself is in ASM, I actually read through it
It may be that I need to introduce a WASM toolchain, or alternatively do what I was trying to avoid and convert them up (upsampling was a source of many headaches with this)
English

@ShimazuSystems maybe its an import sample rate thing? check this:
pitch is like -2 st off on imported version. also, this is a really clear example of the pitch bend mapping
English

@conrad___zeus I have yet to figure out why there's exceptions to some files, and not others 😅
English









