HostDeFi › Fake RPC endpoint attacks, explained
Fake RPC endpoints — when the node lying to you is the attack
Your wallet doesn't check the chain itself — it asks the RPC endpoint you configured. An attacker who controls that answer controls your reality. How the lie works and the 30-second check that breaks it.
Every wallet is blind in the same way: it doesn't connect to "the blockchain," it connects to a URL — the RPC endpoint — and takes whatever answers come back as the truth about the chain. Your balance, your transaction status, the chain ID you're on, the state of every contract your dapp shows you — all of it is the endpoint's word. A malicious or compromised endpoint doesn't need your keys to hurt you. It just needs to lie convincingly, because the signature that actually moves the money is still yours.
What a fake endpoint can actually do
The lies an RPC can tell are the lies the wallet will believe. It can report a wrong chain ID — your wallet thinks it's on Base while the endpoint is serving a fork, a testnet, or a state of the attacker's choosing, which is the payload behind most "wrong network" phishing. It can report fabricated balances — a cloned dapp that shows funds you don't have so you'll deposit to "unlock" them. It can fake a transaction status — claiming a send confirmed when nothing landed, or vice versa, to bait a follow-up action. And it can serve a modified dapp frontend — the endpoint proxies the real interface but swaps the contract calls for drain signatures.
The common shape: you still sign everything yourself. The attack isn't cryptographic — it's epistemic. A fake RPC doesn't take the money; it makes you hand it over while convinced you're doing something else.
The two checks that settle it
Both are one-line JSON-RPC calls, and both are cheap. Chain ID: eth_chainId returns the EIP-155 number the endpoint is serving — it must equal the chain you meant to connect to (Ethereum is 0x1, Base is 0x2105, Arbitrum One is 0xa4b1 — the full table we relay is on /rpc/). An endpoint answering the wrong number is not an alternative route to the chain — it's a different network wearing the name.
Block-height agreement: call eth_getBlockByNumber("latest") on the suspect endpoint and on a second one you already trust. The heights should match within a block or two. A node trailing by minutes is broken; a node answering a different chain's height is a lie. Both checks together take under a minute and catch essentially every fake-endpoint attack — the lie can't survive being cross-examined. The mechanics of reading the dialect itself are in the EVM RPC guide.
The attack's two halves: reads and sends
| What the fake endpoint does | Defense | |
|---|---|---|
| Reads | False chain ID, wrong balances, fake confirmations, poisoned dapp frontend | Cross-check chain ID + block height against a second endpoint |
| Sends | Logs your transaction, routes it to a hostile mempool, feeds it to a sandwicher | Endpoints with a known operator, protected send lanes, tight slippage |
The send half is subtler. Even an honest-feeling endpoint handles your already-signed raw transaction — it can't forge it, but it can see it before the network does, hold it, or route it somewhere worse. That's the same mempool-visibility problem as sandwich attacks, just moved one hop earlier: the endpoint itself is the first observer. On our relay, sends on Ethereum and BNB route through protected lanes first (Flashbots Protect, MEV Blocker — mechanics in the guide) precisely because the read lane and the send lane are different trust surfaces.
Where fake endpoints get in
The infection vector is almost never sophisticated. A chat or forum answer with a "faster" RPC URL. A "we noticed congestion — switch to this endpoint" DM. A dapp tutorial that pastes a network config wholesale, URL included. A "custom RPC" field someone fills from a search result. Each is a URL substitution — your wallet keeps talking to a node, just a lying one. The settings page nobody reads is the attack surface: whatever string is in that field decides your chain reality.
The durable habit: use endpoints with a name and an operator behind them — a documented relay like /rpc/, a known provider, or your own node — and treat any URL handed to you in a DM or comment as hostile until the chain-ID and block checks pass. When something looks wrong in a wallet, the RPC config is the first thing to check, not the last.
The invariant: an RPC is a trusted informant, not a verified one — your wallet renders its answers as fact. Verify the informant: same chain ID as the network, same block height as a second endpoint. If it can't survive the comparison, it isn't a lane — it's a rumor with an HTTPS cert.
And on Solana?
Same attack shape, different dialect — a Solana RPC serves wrong slot state or fabricated account data and the wallet believes it identically. The mechanics of the Solana read surface (and what a healthy endpoint answers) are in the Solana RPC guide; the verification habit is the same one — compare against a second endpoint.
Settle an endpoint in one call
Ask ours for its chain ID, then ask any other lane — the numbers must agree:
curl -X POST https://hostdefi.com/api/rpc/ethereum \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId"}'
# → "0x1" — the answer, verifiable against any second endpoint
Frequently asked
Can a malicious RPC endpoint steal my crypto?
Not directly — an RPC endpoint can't take your keys and can't forge a signature; it only sees what you send it. What it can do is lie about the chain: report a wrong balance, a different chain ID, a fabricated transaction status, or silently route your request to a malicious contract. You still sign the transaction yourself — the attack is making you sign it on false information.
How does a fake RPC endpoint trick a wallet?
The wallet trusts whatever the configured RPC returns. A malicious endpoint answers eth_chainId with a chain it isn't, reports inflated balances so a dapp looks funded, returns false "transaction confirmed" states, or serves a dapp frontend modified to request a drain signature. The wallet UI is just rendering answers — it has no independent way to know the node is lying.
How do I verify an RPC endpoint is honest?
Cross-check it against a second, independent endpoint. Call eth_chainId on both — they must return the same EIP-155 number. Then call eth_getBlockByNumber("latest") on both — the block heights must agree within a block or two. A fake or broken endpoint fails one of the two trivially. Any endpoint that can't survive a two-endpoint comparison shouldn't be in your wallet.
Is it safe to paste a random RPC URL into my wallet?
No — the URL in your wallet's network entry decides what chain your wallet thinks it's on and what every dapp it talks to sees. A random endpoint from a chat or a search result can serve a fake chain, a stale state, or a poisoned frontend. Use endpoints with a known operator or a documented relay; the one check that matters is comparing its answers against a second endpoint you already trust.
Does an RPC endpoint see my private key?
Never on a sane setup — your wallet signs locally and only transmits the already-signed transaction; the endpoint sees ciphertext. The honest risk of a bad endpoint is what it does to your reads (false state) and your sends (routing, logging, or feeding your raw transaction to a hostile mempool), not your keys. An endpoint or dapp that asks you to "sign" to verify or claim anything is the tell that it's after more than routing.