poc: decode Drift protocol hack transaction#241
Draft
prasanna-anchorage wants to merge 5 commits intomainfrom
Draft
poc: decode Drift protocol hack transaction#241prasanna-anchorage wants to merge 5 commits intomainfrom
prasanna-anchorage wants to merge 5 commits intomainfrom
Conversation
Embed the Squads v4 Anchor IDL and decode instructions using parse_instruction_with_idl so transactions show named instructions (vaultTransactionCreate, proposalCreate, proposalApprove, etc.), named accounts, and decoded args instead of raw hex. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deserialize the VaultTransactionMessage from the transactionMessage bytes field using Solana's compact wire format, reconstruct full Instructions, and pass them through the existing visualizer framework so inner program calls (System, Drift, Token, etc.) are displayed with their decoded names and accounts instead of raw hex. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix instruction data_len field in VaultTransactionMessage::deserialize to read as u16 LE instead of u8, matching the Squads v4 on-chain wire format. The previous u8 read consumed one too few bytes, shifting instruction data by one byte and causing inner instruction discriminator mismatches (e.g. Drift updateAdmin showed as "Unknown Instruction"). Also cache the parsed Squads IDL with LazyLock to avoid re-parsing 86KB JSON on every instruction. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add IDL-based visualizer for Drift Protocol v2 (dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH) with 249 instructions. Uses LazyLock to cache parsed IDL. Includes unit tests for IDL loading, discriminator validation, and error handling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When an IDL instruction has both an account and an argument with the same name (e.g. "admin" in Drift's updateAdmin), label them as "Current admin" (account) and "New admin" (argument) in the expanded view to avoid confusion. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacks Squads Multisig (#240) + Drift (#239) presets to fully decode the April 1 2026 Drift Protocol exploit transaction.
Depends on:
data_lenu16 LE fix)What the parser reveals
The $285M Drift exploit used two pre-signed durable nonce transactions. The parser fully decodes both:
Transaction 1 — Create + Approve (signer 1)
https://solscan.io/tx/2HvMSgDEfKhNryYZKhjowrBY55rUx5MWtcWkG9hqxZCFBaTiahPwfynP1dxBSRk9s5UTVc8LFeS4Btvkm9pc2C4H
Transaction 2 — Approve + Execute (signer 2)
https://solscan.io/tx/4BKBmAJn6TdsENij7CsVbyMVLJU1tX27nfrMM1zgKv1bs2KJy6Am2NqdA3nJm4g9C6eC64UAf5sNs974ygB9RsN1
Defense point
The critical signing moment is Transaction 1. The parser decodes the nested
vaultTransactionCreateand revealsDrift: updateAdminwith the new admin address — a signer reviewing this in a wallet would see the admin transfer before approving.By Transaction 2, the inner instructions are already stored on-chain (not in the tx bytes), so
vaultTransactionExecuteonly shows a reference to the vault transaction account. The defense must happen at Tx 1.Key fixes discovered during this POC
VaultTransactionMessage::deserializewas reading instructiondata_lenas u8 instead of u16 LE, causing a 1-byte offset that made inner instruction discriminators unmatchableTest plan
parser_clicorrectly decodes both exploit transactionsupdateAdminshows current and new admin addresses🤖 Generated with Claude Code