Dev.to AI πŸ€– Ai πŸ‘ 0 πŸ“– 2 min read

I built a "what am I signing?" checker for Solana in a weekend

Most people approve crypto transactions blind. A site says "Claim your airdrop!", the wallet pops up, you click Approve... and hope. Wallet drainers count on that. One common Solana trick doesn't even "send" your tokens

I built a "what am I signing?" checker for Solana in a weekend

Most people approve crypto transactions blind. A site says "Claim your airdrop!", the wallet pops up, you click Approve... and hope.

Wallet drainers count on that. One common Solana trick doesn't even "send" your tokens. It quietly hands ownership of your token account to the attacker. No obvious transfer, just gone.

So for the MLH Solana Hackathon I built Clear Sign: paste a transaction (or click a button on a dApp) and see what it will really do before you sign.

πŸ”— Live demo: https://clear-sign-beta.vercel.app/
πŸŽ₯ Video: https://youtu.be/F_w-Fre-uyc
πŸ’» Code: https://github.com/Olacode01/clear-sign

The demo: two buttons, one trap

The demo is a fake "🎁 FreeSOL Airdrop" site:

  • Claim 0.01 SOL β†’ βœ… SAFE: "+0.01 SOL to your wallet."
  • Claim 500 USDC bonus πŸ”₯ β†’ πŸ›‘ DO NOT SIGN: it takes 0.6 SOL and hands control of your 240 USDC to an unknown wallet.

Same-looking buttons, very different transactions.

How it works: simulate β†’ check β†’ explain

1. Simulate (Solana does the heavy lifting)

Solana can run a transaction against live chain state without a signature and return what every account would look like afterwards. I read the accounts before, simulate, and compare:

const before = await conn.getMultipleAccountsInfo(keys);
const sim = await conn.simulateTransaction(tx, {
  sigVerify: false,
  replaceRecentBlockhash: true,
  accounts: { encoding: "base64", addresses },
});
// decode token accounts in `before` and `sim.value.accounts`, then diff

It's fast and free, so the check fits right in the gap between "click" and "approve".

2. Check (fixed rules decide the risk)

Plain TypeScript rules flag:

  • a token account's owner changing β†’ critical
  • a new spending approval (delegate)
  • a token account being closed
  • more than half of a balance leaving
  • calls to unrecognised programs

3. Explain (AI makes it human)

Gemini turns the result into two or three plain-English sentences, contrasting what the site claims with what actually happens.

The design choice I'm proudest of

The rules set the risk level. The AI only explains it.

The model is given the verdict and told it can't change or soften it. A cleverly worded transaction (or a prompt-injection-style memo) can't talk the AI into calling a drainer "safe". And if the AI is down, the app falls back to a rules-only explanation, so the warning never depends on the model.

What tripped me up

  • Devnet SOL: faucet rate limits were my first wall.
  • Cryptic errors: failed to sanitize accounts offsets correctly just meant my demo addresses weren't set up yet.
  • AI reliability: one model was overloaded, another was retired, and "thinking" models sometimes returned empty text. Fix: try several models in order, add timeouts, and keep the rules fallback.

What's next

  • A wallet-adapter hook or extension so the check runs automatically before every signature
  • Token-2022 and address lookup table support
  • Known program/token registries, then mainnet

Stack

Next.js Β· @solana/web3.js Β· @solana/spl-token Β· Gemini Β· Vercel Β· Solana devnet. Built solo, pair-programming with Claude Code.

If you've ever clicked "Approve" and hoped for the best, I'd love your feedback. What other drainer patterns should it catch? πŸ‘‡

πŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.