SignLens

Incidents › The Drift takeover, April 2026

The Drift takeover: two signatures, read by SignLens

Published

On 1 April 2026 an attacker took control of Drift Protocol, a perpetuals exchange on Solana, and withdrew between $270 and $286 million by different estimates. No code was exploited and no seed phrase stolen: two members of the multisig that controlled Drift each signed a transaction that handed control to the attacker. Both transactions are on chain. This is what they say.

What happened

The setup
Drift's admin, the key that can list markets, set their oracles and change withdrawal limits, was a vault of a Squads multisig: two approvals of five members, with no time lock since late March. On 24 and 31 March (UTC) another wallet created two durable nonce accounts and made two council members their authorities. A transaction built on a durable nonce never expires.
The first signature
One member signed, alone, a transaction that creates a multisig transaction whose one step is Drift's updateAdmin to the attacker's key, proposes it and approves it.
The second signature
Another member signed, alone, a transaction that approves that proposal and executes it.
16:05:18 and 16:05:19 UTC
The attacker submitted both, one second apart. Drift's admin became H7PiGqqUaanBovwKgEtreJbKmQe6dbq6VTrw6guy7ZgL. Within minutes it listed a market for a token it controlled, priced by an oracle it controlled, raised the withdrawal limits and withdrew.
How the signatures were obtained
Drift has said the attackers spent about six months building trust in person as a quantitative trading firm, and that the likely ways in were a cloned code repository and a test app presented as a wallet product. Drift, with the Security Alliance's SEAL 911, says with medium-high confidence that it was the North Korea-linked group behind the Radiant Capital hack of 2024, which Mandiant attributes to UNC4736; Mandiant has not formally attributed the Drift attack. What the signers' screens showed has not been made public.

The first signature, as SignLens reads it

SignLens reads the proposal's transaction inside the signature and explains its step as it would any instruction: it hands the admin of Drift to an address that is not the signer's. Two high findings: what an admin can do over every user's deposits, and that the signature never expires.

Warning

3 actions

  1. Propose for AiLG…PKrW (Hand the admin of Drift to H7Pi…7ZgL)
  2. Create proposal #7 for the transaction proposed in instruction 2
  3. Approve proposal #7 (the transaction proposed in instruction 2)

What SignLens found

What this does

Full text, as the engine prints it
3 actions: Propose for AiLG…PKrW (Hand the admin of Drift to H7Pi…7ZgL); Create proposal #7 for the transaction proposed in instruction 2; Approve proposal #7 (the transaction proposed in instruction 2)
WARNING: review the findings before approving

Findings:
  [HIGH] Proposal step 1: Hands the admin of the whole Drift protocol to an account that is not yours: the admin can add markets, set their oracles and collateral weights, and raise withdrawal limits, over every user's deposits (instruction 2)
  [HIGH] This signature has no time limit: anyone holding the signed transaction can submit it at any later time, until the nonce account is advanced

== Propose multisig transaction | Squads multisig v4
  Multisig: 2LW6PSEjp81xSEttWwXDB6Etb1eKdhYPbFEojYbyhx88
  Vault: Vault 0 of multisig 2LW6…hx88 (AiLG…PKrW)
  Transaction account: 2QmMUBZYv2Ssm6ED73Gapt8cgn9u1HQbPaJtfYdDDAwc
  Proposed by: Your wallet (39Jy…7Aq8)
  Rent paid by: Your wallet (39Jy…7Aq8)
  Executes: only once the multisig's approval threshold is met and someone executes it; nothing moves now
  Steps: 1

==== Step 1: Change the protocol admin | Drift Protocol v2 (descriptor reviewed 2026-10-25, upgradeable by 8jj7…BMai)
  New admin: H7PiGqqUaanBovwKgEtreJbKmQe6dbq6VTrw6guy7ZgL
  Current admin: Vault 0 of multisig 2LW6…hx88 (AiLG…PKrW)
  Drift state: 5zpq7DvB6UdFFvpmBPspGPNfUGoBRRCE2HHg5u3gxcsN

== Create proposal | Squads multisig v4
  Multisig: 2LW6PSEjp81xSEttWwXDB6Etb1eKdhYPbFEojYbyhx88
  Proposal: J1w1U5BB9W4Tnf2NhrcnTmV5t6iZugXSkujYKadwxti8
  Transaction index: 7
  Content: the vault transaction created in instruction 2 of this transaction
  Proposed by: Your wallet (39Jy…7Aq8)
  Rent paid by: Your wallet (39Jy…7Aq8)
  Starts as draft: no

== Approve proposal | Squads multisig v4
  Multisig: 2LW6PSEjp81xSEttWwXDB6Etb1eKdhYPbFEojYbyhx88
  Proposal: J1w1U5BB9W4Tnf2NhrcnTmV5t6iZugXSkujYKadwxti8
  Content: proposal created in instruction 3 for the vault transaction created in instruction 2, both in this transaction
  Member: Your wallet (39Jy…7Aq8)

== Also [collapsed]
  Advance durable nonce: Nonce account: 7s7s6saC5LHZoLyBXLM3pCjpWaA7meyQdP8NiH9ktAeC
  Advance durable nonce: Authority: Your wallet (39Jy…7Aq8)

== Signers
  Fee payer: Your wallet (39Jy…7Aq8)

== Fee
  Total: 0.000005 SOL
  Base: 0.000005 SOL
  Rent deposits: the rent of 2 accounts of unknown size; refunded to whoever closes the accounts

== Validity
  Expires: when the nonce account is advanced, with no time limit
  Nonce account: 7s7s6saC5LHZoLyBXLM3pCjpWaA7meyQdP8NiH9ktAeC

Effects:
  - Once approved, Vault 0 of multisig 2LW6…hx88 (AiLG…PKrW) would: Give the admin authority over 5zpq7DvB6UdFFvpmBPspGPNfUGoBRRCE2HHg5u3gxcsN to H7PiGqqUaanBovwKgEtreJbKmQe6dbq6VTrw6guy7ZgL
  - Create 2QmMUBZYv2Ssm6ED73Gapt8cgn9u1HQbPaJtfYdDDAwc, managed by Squads multisig v4 (SQDS…2pCf)
  - Create J1w1U5BB9W4Tnf2NhrcnTmV5t6iZugXSkujYKadwxti8, managed by Squads multisig v4 (SQDS…2pCf)
  - You pay a fee of 0.000005 SOL
  - Valid until nonce account 7s7s6saC5LHZoLyBXLM3pCjpWaA7meyQdP8NiH9ktAeC is advanced, with NO TIME LIMIT (durable nonce)

Raw: solana legacy (515 bytes)
  digest: 040ee7c2d4ddf57174105c4c6624082947df4b57cfccf98abe1bbc958c3076cf
Mainnet transaction 2HvM…2C4H, slot 410,344,005. Explained for 39Jy…7Aq8 as the signer, by the SignLens engine 0.3.0, on 2026-11-01. How to read this.

The second signature, as SignLens reads it

The second member approved and executed the proposal the first signature creates. Its content is not in the bytes they signed, so SignLens cannot say what it does, and says that, beside the durable nonce. Nor was it anywhere on chain to be read when they signed: the proposal and the transaction it stores were created by the first signature, submitted at 16:05:18, and the second, like the first, had been signed in advance on a durable nonce.

Warning

2 actions

  1. Approve proposal J1w1…xti8
  2. Execute proposal J1w1…xti8

What SignLens found

What this does

Full text, as the engine prints it
2 actions: Approve proposal J1w1…xti8; Execute proposal J1w1…xti8
WARNING: review the findings before approving

Findings:
  [HIGH] This would approve a multisig proposal whose content is on chain, not in the signed bytes; SignLens cannot show what it does (instruction 2)
  [HIGH] This would execute a multisig proposal whose content is on chain, not in the signed bytes; SignLens cannot show what it does (instruction 3)
  [HIGH] This signature has no time limit: anyone holding the signed transaction can submit it at any later time, until the nonce account is advanced

== Approve proposal | Squads multisig v4
  Multisig: 2LW6PSEjp81xSEttWwXDB6Etb1eKdhYPbFEojYbyhx88
  Proposal: J1w1U5BB9W4Tnf2NhrcnTmV5t6iZugXSkujYKadwxti8
  Content: on chain, not in these bytes
  Member: Your wallet (6UJb…u924)

== Execute vault transaction | Squads multisig v4
  Multisig: 2LW6PSEjp81xSEttWwXDB6Etb1eKdhYPbFEojYbyhx88
  Proposal: J1w1U5BB9W4Tnf2NhrcnTmV5t6iZugXSkujYKadwxti8
  Content: on chain, not in these bytes
  Member: Your wallet (6UJb…u924)

== Also [collapsed]
  Advance durable nonce: Nonce account: EmYEryTDXtuVCxrjNqJXbiwr4hfiJajd4g5P58vvhQnc
  Advance durable nonce: Authority: Your wallet (6UJb…u924)

== Signers
  Fee payer: Your wallet (6UJb…u924)

== Fee
  Total: 0.000005 SOL
  Base: 0.000005 SOL

== Validity
  Expires: when the nonce account is advanced, with no time limit
  Nonce account: EmYEryTDXtuVCxrjNqJXbiwr4hfiJajd4g5P58vvhQnc

Effects:
  - You pay a fee of 0.000005 SOL
  - Valid until nonce account EmYEryTDXtuVCxrjNqJXbiwr4hfiJajd4g5P58vvhQnc is advanced, with NO TIME LIMIT (durable nonce)

Would read, to explain more:
  - J1w1U5BB9W4Tnf2NhrcnTmV5t6iZugXSkujYKadwxti8: the proposal: its index names the transaction it runs
  - 2QmMUBZYv2Ssm6ED73Gapt8cgn9u1HQbPaJtfYdDDAwc: the transaction the proposal runs

Raw: solana legacy (432 bytes)
  digest: ee7706555a2bed3f52dde729942482697f4aef89b2e733ee1e75b78b037a2af5
Mainnet transaction 4BKB…RsN1, slot 410,344,009. Explained for 6UJb…u924 as the signer, by the SignLens engine 0.3.0, on 2026-11-01. How to read this.

What this does and does not show

The handover was in the bytes, in plain words: anyone reading the first transaction could see that it gave Drift away, and that both signatures stayed valid forever. That is the claim, and the only one. Whether SignLens would have stopped the attack, nobody can say: if the signers' devices or the app they signed with were compromised, as Drift's account suggests, a browser extension may never have been in the path.

Try it: install SignLens for Chrome or Firefox.

Sources