The Anatomy of a Solana Wallet Drainer: Owner Reassignment, Durable Nonce Tricks, and Blinks Phishing
Solana users lost over $90 million to phishing in the first half of 2025. By early 2026, the drainer kits have evolved again — and this time, they're bypassing wallet simulations entirely.
This isn't about smart contract bugs. It's about weaponizing legitimate Solana features against users who trust what their wallet shows them.
Let's dissect the three most dangerous wallet-draining techniques active on Solana right now, and what developers and users can do to defend against them.
Attack #1: The assign Instruction — Silent Owner Reassignment
Why Solana's Account Model Makes This Possible
On Ethereum, your EOA is controlled by whoever holds the private key. Period. On Solana, every account has an explicit Owner field that determines which program has write access to it. By default, your wallet account is owned by the System Program.
Here's the critical detail most users don't know: the assign instruction can change the Owner field of any account the signer controls.
// The Solana System Program's assign instruction
pub fn assign(
pubkey: &Pubkey, // Account to reassign
owner: &Pubkey, // New owner program
) -> Instruction
How Attackers Exploit This
- Phishing entry point: Victim clicks a link to "claim an airdrop" or "verify for an allowlist"
- Benign-looking transaction: The wallet simulation shows no token transfers, no balance changes — everything looks safe
-
Hidden
assigninstruction: Buried in the transaction is a System Programassigncall that transfers the account's Owner field to an attacker-controlled program - Delayed drain: The attacker now controls the account. They can drain SOL, SPL tokens, and NFTs at any time — the victim's private key is irrelevant
Why Wallet Simulations Miss It
Most wallet simulations focus on balance changes. The assign instruction doesn't move tokens — it changes who controls the account. The simulation shows:
✅ No SOL transferred
✅ No tokens transferred
✅ No approvals granted
The user signs with full confidence. Their account is already gone.
The SlowMist Analysis
SlowMist's research revealed that this attack mirrors the "malicious multisig" pattern previously seen on TRON, where administrative rights are silently reconfigured. On Solana, it's even more dangerous because:
- No multisig UI exists to show ownership changes
- The
assigninstruction is a core System Program feature, not an exotic edge case - Once reassigned, the original private key holder has zero recovery options
Attack #2: Durable Nonce + Contract Upgrade — The Time Bomb
The Setup
Normal Solana transactions expire after ~60-90 seconds (the blockhash lifetime). But durable nonces allow transactions to remain valid indefinitely. They're designed for legitimate use cases — offline signing, multi-party approvals, scheduled execution.
Attackers have weaponized this feature into a two-phase attack:
Phase 1: The Innocent Signature
User signs a durable-nonce transaction that:
├── Advances the nonce (required for durable nonce txs)
├── Calls a contract method: mint_nft()
└── The contract's mint_nft() is genuinely benign at signing time
The wallet simulates the transaction. It calls mint_nft() on the current contract code. Everything checks out — the user gets an NFT, no funds leave.
Phase 2: The Upgrade
The attacker doesn't broadcast the transaction yet. Instead, they:
- Upgrade the target contract (Solana programs are upgradeable by default)
- The new
mint_nft()function now includestransferinstructions that drain the caller's wallet - Now they broadcast the pre-signed transaction
When the transaction executes, it runs against the new, malicious contract code. The simulation the user saw was accurate at the time of signing — but the contract changed underneath.
Why This Is Almost Undetectable
Timeline:
T+0s User signs transaction → Simulation: ✅ Safe
T+30min Attacker upgrades contract
T+31min Attacker broadcasts pre-signed transaction
T+31min Transaction executes against malicious contract → 💀 Drained
No wallet can simulate what a contract will become. The simulation was truthful — it just became stale.
Mitigation for Developers
If you're building a program that interacts with user funds:
// Always verify the program hasn't been upgraded since the user's intent
// Use immutable programs where possible
// If upgradeability is required, implement a timelock
#[account(
constraint = program_data.upgrade_authority_address == Some(EXPECTED_AUTHORITY)
@ ErrorCode::UnexpectedUpgradeAuthority,
constraint = program_data.slot == EXPECTED_DEPLOYMENT_SLOT
@ ErrorCode::ProgramUpgraded,
)]
pub program_data: Account<'info, ProgramData>,
For users: never sign durable-nonce transactions from untrusted sources. If a dApp asks you to sign something that doesn't expire, treat it like handing someone a signed blank check.
Attack #3: Malicious Blinks — One-Click Wallet Drains on Social Media
What Are Blinks?
Solana Actions and Blinks (Blockchain Links) let developers embed executable transactions directly in social media posts, websites, and messaging apps. Click a Blink, approve in your wallet, and the action executes on-chain.
The UX is incredible. The phishing surface is terrifying.
The Attack Flow
1. Attacker creates a malicious Action endpoint
2. Wraps it in a Blink that says "Claim your 500 SOL airdrop!"
3. Posts it on X/Twitter, Discord, Telegram
4. Victim clicks → wallet opens → transaction preview shows...
what exactly?
The problem: Blinks execute arbitrary transaction payloads returned by the Action endpoint. The endpoint can return any valid Solana transaction, including:
- Token approvals to attacker addresses
-
assigninstructions (Attack #1) - Durable nonce transactions (Attack #2)
- Direct SOL transfers disguised in complex instruction bundles
The Registry Problem
Solana maintains a Blinks registry of verified Action providers. But:
- Not all wallets enforce registry checks
- Users often click first, verify never
- Attackers register legitimate-looking domains that pass initial review
- Social engineering ("Limited time! Only 100 claims left!") bypasses rational judgment
Real-World Example: The Fake Mint Blink
In Q1 2026, a Blink circulating on X promised "free mint" for an NFT collection. The Action endpoint returned a transaction with three instructions:
Instruction 1: Create associated token account (looks normal)
Instruction 2: Transfer 0.01 SOL for "gas" (seems standard)
Instruction 3: assign(victim_account, attacker_program)
Most users saw "Create account + small fee" and approved. Their wallets were drained within minutes.
Defense Playbook: What Actually Works
For Users
| Risk | Defense | Difficulty |
|---|---|---|
| Owner reassignment | Use a hardware wallet that shows raw instructions | Medium |
| Durable nonce traps | Never sign durable-nonce txs from unknown sources | Easy |
| Blinks phishing | Only interact with registry-verified Blinks | Easy |
| All of the above | Use a burner wallet for all interactions | Easy |
The Burner Wallet Strategy:
Main wallet (cold storage): 95% of assets
├── Hardware wallet or multisig
├── Never connects to dApps
└── Only receives transfers from hot wallet
Hot wallet (daily use): 5% of assets
├── Connects to dApps, signs transactions
├── Funded with only what you can afford to lose
└── Regularly sweep profits back to cold storage
Burner wallet (disposable): Dust only
├── Used for airdrops, new mints, untrusted dApps
├── Contains <$50 at any time
└── Abandoned and replaced regularly
For Developers
- Make your programs immutable once they're stable. If your program doesn't need upgrades, revoke the upgrade authority permanently:
solana program set-upgrade-authority <PROGRAM_ID> --final
- If upgradeability is required, implement a timelock:
pub struct UpgradeTimelock {
pub proposed_authority: Pubkey,
pub proposal_time: i64,
pub timelock_seconds: i64, // Minimum 48 hours recommended
}
- Implement transaction guards that check for suspicious instruction patterns:
// Reject transactions that include assign instructions
// alongside your program's instructions
fn validate_transaction_context(ctx: &Context) -> Result<()> {
let instructions = get_processed_sibling_instruction(0);
for ix in instructions {
if ix.program_id == system_program::ID {
// Check if it's an assign instruction (discriminator = 1)
if ix.data.first() == Some(&1) {
return Err(ErrorCode::SuspiciousInstruction.into());
}
}
}
Ok(())
}
- Emit events for ownership changes so monitoring tools can flag suspicious activity:
#[event]
pub struct OwnershipAlert {
pub account: Pubkey,
pub old_owner: Pubkey,
pub new_owner: Pubkey,
pub slot: u64,
}
For Wallet Developers
The biggest gap in current wallet UX is the failure to surface non-financial state changes. Wallets should:
-
Flag
assigninstructions with a prominent red warning: "This transaction will change who controls your account" - Detect durable nonce usage and warn: "This transaction does not expire — the contract could change before execution"
- Show program upgrade status: "This program was last upgraded 3 hours ago" or "This program is immutable ✅"
- Verify Blinks against the official registry and display clear trust indicators
The Bigger Picture
These attacks share a common theme: they exploit the gap between what users see and what actually happens on-chain. Solana's account model is powerful, but its flexibility creates attack surfaces that don't exist on simpler chains.
The $90M+ lost to Solana phishing in 2025 wasn't caused by protocol bugs. It was caused by:
- Users trusting wallet simulations as absolute truth
- Developers shipping upgradeable programs without timelocks
- Wallets optimizing for "clean" UX over transparent disclosure
- Social platforms failing to filter malicious Blinks
The tools to prevent every attack in this article already exist. The challenge is getting the ecosystem to adopt them before the next $100M disappears.
Key Takeaways
-
The
assigninstruction can silently transfer control of your Solana account — and wallet simulations won't catch it - Durable nonce + contract upgrade creates a time-bomb attack that defeats simulation-based protection entirely
- Blinks are phishing delivery mechanisms that embed transaction payloads directly in social feeds
- Burner wallets are the single most effective user defense — isolate assets from interaction risk
- Developers must choose immutability or implement timelocks — there's no safe middle ground
This article is part of the DeFi Security Research series. Follow @ohmygod for weekly deep dives into blockchain security vulnerabilities, audit techniques, and defense strategies.
Top comments (0)