Loading banner...

dApp Frontend Attack: How the Polymarket Drain Happened

Tired Eyes? Hit Play.
Author:
Funk D. Vale
Published:
June 29, 2026
Updated:
June 29, 2026
dApp Frontend Attack: How the Polymarket Drain Happened
TL;DR
A dApp has two halves: an on-chain smart contract that can be audited, and a website frontend that builds the transaction your wallet signs and can be changed or compromised at any time. When a legitimate site's frontend is supply-chain compromised, the URL and the contract audit both still pass while the poisoned page swaps in a malicious call, the way Polymarket lost about $3.1M on contracts that never failed. The only reliable defense is reading the raw transaction your wallet shows (the function, the spender, the amount) before signing, and keeping standing token approvals minimal.

Is It Safe to Connect Your Wallet to a dApp?

You did everything the guides tell you. You typed the address by hand instead of clicking a link. You saw the lock icon. You had used the site many times before.

Then you signed one transaction, and the wallet emptied.

Nothing in the smart contract failed. It read your request, checked your signature, and moved the funds exactly as written. The attack never lived in the contract. It lived in the website you connect your wallet to.

This is a Kodex walkthrough with Eunha, who reads what a system does by what it touches, not by what it claims. The question the two of you will sit with is the one almost everyone answers too fast: is it safe to connect your wallet to a dApp?

Eunha does not start with the wallet. She starts with the page. "Before you click Confirm," she says, "tell me which half of this app you are actually trusting."

A poisoned dApp page, not a broken contract

On June 27, roughly $3.1 million left user wallets on the prediction market Polymarket without a single line of its on-chain code breaking. CoinDesk reported the drain hit eleven wallets, with the stolen balances converted into about 1,893 ETH and bridged from Polygon to Ethereum. The contracts did exactly what they were written to do. The compromise sat one layer above them, in the site's frontend, where a third-party vendor's code had been poisoned with malicious JavaScript.

Eunha sets the two facts next to each other. "The code on the blockchain was honest," she says. "The code in your browser was not. Both ran. You signed the second one."

Here is what unsettles people about it. The victims were not phished. No look-alike domain, no fake clone, no typo in the address bar. They were on the real Polymarket, the site they had used before, and they approved the transaction themselves. The page simply built a different request than the one they thought they were making.

This is not the kind of theft where someone steals your keys. No seed phrase leaked. No password was guessed. You hold your keys the whole time, and you use them to sign your own loss.

Polymarket removed the compromised dependency and pledged full refunds to the affected wallets. It was the platform's second incident in weeks, after a separate late-May breach of internal payout wallets. (A current CFTC inquiry into the company is a different matter, about marketing, not this attack. Keep the two apart.) By DefiLlama's tracking, frontend and account compromises like this now lead DeFi incidents by count, even when each one drains less than a headline contract exploit.

Strip the news down to its shape. A real site you trusted served you a real transaction that did real damage.

Nothing had to be hacked in the way you picture hacking.

Where the transaction you sign gets built

A dApp is not one thing. It is two.

One half is the smart contract: code deployed on a blockchain, fixed in place, the same for everyone who calls it, and often audited line by line. The other half is the frontend: a website, running in your browser, served off ordinary web infrastructure. That half builds the transaction. You click a button, and the page assembles the actual call, the function, the destination, the amount, then hands it to your wallet to sign.

Your wallet does not know your intention. It knows the call it was handed.

"You think you are clicking Place Bet," Eunha says. "Your wallet sees a function, an address, and a number. It will sign whatever those three are, because signing them is its whole job."

The contract is the half that cannot change between visits. The frontend is the half that can change on every load. It pulls in third-party libraries, wallet kits, analytics, dozens of dependencies maintained by people you will never meet and cannot vet. A single page can load code from a dozen origins, and each one is a place the build can be poisoned upstream, before it ever reaches you. Compromise any one of them and the page that loads today is not the page that loaded yesterday, even though the address in your bar is identical to the character.

That asymmetry is the entire story. You checked the part that holds still. The attack came from the part that moves.

It is the same shape as malware riding into your machine through a dependency, except here the poisoned dependency runs inside the website instead of on your computer. The trust you extend to the brand on the page quietly extends to every library that page loads.

Why the right URL and a real audit both miss it

Walk your usual defenses past Eunha one at a time, and watch each one pass while the money still leaves.

You check the URL. It is correct. The real domain was compromised, not impersonated, so the address bar tells you the truth, and the truth does not help.

You check whether the contract is verified and audited. It is. The contract was never the problem. The page swapped the call before it ever reached the chain.

You see HTTPS and the padlock. That confirms the connection is encrypted. It says nothing about whether the code arriving over that connection is honest. An encrypted delivery of a malicious script is still a malicious script.

You reach for the hardware wallet, the one that keeps your keys offline. It signs the calldata the page built. It cannot read your mind and notice the destination is wrong. Cold storage protects the key, not the intent behind the click.

None of this announces itself. The malicious call arrives looking like every other call you have approved, in the same wallet popup, under the same Confirm button. There is no warning banner, because nothing in the chain of software knows anything is wrong. The site believes it is serving its own code. Your wallet believes it is signing your intent.

Right site. Right contract. Wrong call.

"Every check you ran answers a different question than the one that matters," Eunha says. "They all ask, is this the real place? The question is, is this the real transaction?"

Securing the wallet itself is necessary, and it is not the cure for this, because a secured wallet still signs what it is handed. The defenses you were taught are not wrong. They are aimed one layer below where this attack lives.

What the swapped-in call usually asks for

When a poisoned frontend rewrites your transaction, it tends to ask for one of a few things, because a few things are enough.

The common one is an approval. ERC-20 tokens let you grant a spender permission to move your tokens on your behalf, through a function like approve, a gasless permit signature, or setApprovalForAll for an NFT collection. Grant that permission to an address the attacker controls, and they can pull the tokens later, on their own schedule, with no further signature from you. The page dresses the approval up as the action you came to perform.

The sneakiest version is a gasless signature. A permit or Permit2 approval is signed off-chain, so it never appears as a pending transaction and costs no gas, which makes it feel even less like an action you took. One signature, no fee, and the allowance is live.

The other is a direct transfer, disguised as a deposit or a claim.

Eunha slows you down on the first one. "An approval does not feel like losing money," she says. "Nothing leaves in that moment. You sign, the balance still reads the same, and you close the tab. The door is just open now, and it stays open."

That is why a standing allowance is the quiet danger. It sits there long after you have forgotten the session, and a single forgotten approval to the wrong contract is all a drain needs to work. It is the same open door that makes a habit of revoking token approvals worth keeping, long after the page that asked for it is closed.

The shape to remember: the dangerous signature is not the one that sends your funds. It is the one that quietly permits someone else to.

Reading the call before you sign it

There is one defense the attack cannot route around, and you already hold it. Your wallet shows you the transaction before you sign. The discipline is to actually read it instead of clicking through.

Three fields decide whether a call is safe to sign.

The function. Is this an approve or a setApprovalForAll when all you meant to do was swap once? A permission verb deserves a second look every single time.

The spender or destination. Is it the contract you expected, or an address you have never seen before? A swap that suddenly wants to send somewhere unfamiliar is the tell.

The amount. Is it the figure you typed, or an unlimited allowance hiding behind a friendly Confirm button? Unlimited means your whole balance, for as long as the approval stands.

If any of the three does not match what you just did, reject it. A rejected transaction costs you nothing but a moment.

"Read the call, not the page," Eunha says. "The page is the pitch. The call is the contract you are actually signing."

Modern wallets help here. Many now decode a request into plain language and simulate what it would do to your balances before you approve. Lean on that preview, and be extra careful when a wallet cannot decode a request and asks you to sign raw, unreadable data. Signing what you cannot read is how the worst of these end.

Two habits shrink the damage even on the day you slip. Keep approvals minimal, so a poisoned page finds less to take and an old allowance cannot be turned against you. And keep a separate wallet for dApp activity, holding only what you are willing to put on the table, so the rest of your funds never sit behind a single bad signature. A block-explorer approval checker or a revocation tool makes the standing-permission audit routine. The tool you pick matters far less than the habit of looking.

This is the core of the Survival Framework: assume something will eventually compromise the screen in front of you, and sign as if it already has.

Eunha lays the two halves of the app side by side.

The page (frontend)The contract (on-chain)
Runs in your browserRuns on the blockchain
Can change on every visitFixed once it is deployed
Anyone who compromises the site or a dependency can rewrite itNo one can alter it after launch
Your wallet never checks it, it signs the call the page hands overYour wallet just executes the code as written
Reading the raw call is what protects youThe audit is what protects you

One side you can audit once and trust. The other you have to read every time you sign.

So is it safe to connect your wallet to a dApp?

Connecting your wallet is safe. Reading is safe. A read-only connection lets a site see your public address and your balances, and seeing cannot move anything you own.

Signing is where the risk lives.

So the honest answer is not yes and it is not no. It is this: connecting, yes; signing, only after you read. The real site you trust can still serve you a bad call, because the half of it that builds the call is not the half that got audited. That does not make dApps unusable. It makes one habit non-negotiable. Every signature gets read, on every site, no matter how many times you have used it before.

Eunha closes the loop. "You cannot trust a page into being honest," she says. "You can only read the call and decide. That is the whole job, and it is yours, not the site's."

The contract held. The page did not. The signature was always the door, and your own eyes are the lock.

Questions worth asking before you sign

Can a legitimate crypto website drain your wallet?

Yes, if its frontend is compromised. The site does not have to be fake. When an attacker poisons a third-party dependency the real site loads, the genuine domain can serve you a wallet-draining transaction. Your defense is not spotting a fake site. It is reading the call before you sign it, even on a site you trust completely.

Does a hardware wallet protect you from a frontend hack?

It protects your keys, not your intent. A hardware wallet keeps your private keys offline and signs the transaction the website built. If the page constructed a malicious approval, the device signs that approval as faithfully as it would a legitimate one. It guards the key. It cannot judge the call.

How do I verify a transaction before I sign it?

Read three fields in the wallet prompt: the function (is it an approval you did not intend?), the spender or destination (is it the address you expected?), and the amount (is it your figure, or an unlimited allowance?). If any one does not match what you just did, reject it. For a deeper walkthrough, MetaMask's guide to whether a contract is safe to interact with covers reading a request in detail.

Was Polymarket's smart contract hacked?

No. Polymarket's contracts ran as designed. The compromise was in the frontend, a malicious script injected through a third-party vendor, which built fraudulent transactions that users then approved. The funds moved through valid signatures on working code, which is exactly why URL checks and audit checks did not catch it.

What is a frontend supply-chain attack in crypto?

It targets the third-party code a legitimate website depends on, rather than the site or the blockchain directly. By compromising one dependency in the build, the attacker changes what the real page does, in this case making it construct wallet-draining transactions, without ever touching the smart contract or the domain you typed.

Can You Beat The System

Better trading starts with better insight....