← All case studies

Morpher Wallet: A Chain-Agnostic Signer at 681k Scale

CTO at Morpher Labs · 2020 - Present

Why we shipped a self-custodial web wallet that doesn't know what chain it's on, and how the RPC-intercepting signer architecture made it work for ~681k accounts across every EVM chain we ever integrated.

Wallets
Account Security
EVM
Architecture

Problem

The Morpher trading product needed to feel custodial. New users who had never used MetaMask had to be able to deposit, sign trades, and withdraw without the friction of installing a browser extension or learning seed-phrase hygiene. At the same time, the wallet had to remain self-custodial. Holding user keys server-side was off the table for compliance and trust reasons.

The second pressure was multi-chain support. We started with Ethereum, then needed to add our own Plasma sidechain, then Polygon, and later Base. If every new chain meant a new wallet build and a new release cycle, we would burn out the product team and ship slowly behind market moves.

Constraints

The wallet had to live in the browser. No native installs, no CLI tools, no extensions. That capped the cryptographic surface to what is reasonable to do with WebCrypto and JavaScript.

It had to be self-custodial. Keys live in encrypted local storage. The server never sees the unencrypted private key.

It had to scale to hundreds of thousands of accounts. We could not afford a per-user provisioning step that involved engineering operations.

And it had to remain forward-compatible with chains we hadn't integrated yet, including ones that wouldn't exist for years.

Architecture

The core decision: split signing from RPC.

Most wallet stacks bundle the two. The wallet object knows about a chain because it has an RPC endpoint baked in, and it both signs and broadcasts transactions. We did the opposite. The Morpher Wallet only signs. The RPC sits outside the wallet, owned by the application layer.

The wallet is an encrypted, double-salted keystore. Keys are encrypted with a key derived from the user's password and a per-user salt, then re-wrapped with a server-supplied salt that is fetched fresh on every login. Compromise of either side alone does not yield the key. The server salt also gives us a kill switch for compromised accounts.

The signer intercepts at the JSON-RPC level. When the application asks for an eth_sendTransaction or personal_sign, the wallet pops up, decrypts the key in memory, signs, and hands the signed payload back. The RPC layer takes that signed payload and broadcasts it to whichever chain the app currently points at.

Because the wallet does not know what chain it's on, adding a new EVM chain meant adding an RPC entry on the application side. Zero wallet changes.

My role

Architecture and the decision to split signing from RPC. Implementation of the keystore, the encryption scheme, and the signer interception. Security review of the cryptographic choices. I also owned the recovery flow, which is its own design exercise once you commit to never seeing the user's key.

Outcome

About 681,000 wallets created over the lifetime of the product. Every EVM chain we ever connected the platform to worked without a wallet release. When we moved trading volume from our in-house Plasma chain to Polygon and later Base, the wallet did not change. We changed the RPC.

Internal hiring also benefited. Engineers could reason about the wallet as a pure signer, not as a moving chain target. That made onboarding fast and reduced the surface area for security mistakes.

Tradeoffs

The browser is the floor. We carried a phishing and XSS budget that we mitigated at the application layer (CSP, origin pinning, transaction preview UI), but we never pretended the threat model was the same as a hardware wallet.

Double salting is more complex than a single password-derived key. We accepted that for the kill-switch and for resistance against offline brute force on a leaked database. It also forced us to be careful about the login round trip and how we handle network failures during decryption.

Splitting signing from RPC means the application layer carries chain configuration. That is a feature for us, but it puts more responsibility on the app. A wallet that abstracts chains entirely is cleaner for users who want to manually pick a chain in a dropdown. We did not have that user story; our app always knew which chain a given action belonged to.

If I were building this again today, I would still split signing from RPC. The forward compatibility paid for itself many times over. I would also seriously evaluate ERC-4337 account abstraction as a complementary layer, especially for paymaster-sponsored gas, which would have improved our onboarding even further.