Krtek Wallet + 2FA
Easy to use wallet with 2FA that feels like web2
Created on 9th May 2026
•
Krtek Wallet + 2FA
Easy to use wallet with 2FA that feels like web2
The problem Krtek Wallet + 2FA solves
Demo Video: https://drive.google.com/drive/folders/1sm5W6mXupJr4u48jPRc-gyBWgD5eg
A self-custodial EVM wallet for non-crypto-natives.
No seed phrase, ever. Signing in with ENS and password derives your owner key in the browser
(Argon2id), funds live in an ERC-4337 smart account, and a custom paymaster
sponsors gas so users never need ETH to make their first move.
What's built
1. Password-only login → on-chain smart account
Argon2id over (password, sha256("krtek.wallet.v1.password-key:" + handle))
deterministically derives a secp256k1 owner key in the browser. The owner key
lives only in tab memory; nothing secret touches localStorage. The same
password+handle on any device yields the same wallet — a real ERC-4337 v0.7
SCA at a CREATE2 address. See web/src/lib/password-key.ts,
PASSWORD_LOGIN.md.
2. Custom verifying paymaster (gasless onboarding)
A Bun service signs paymasterAndData for every UserOp; the on-chain
KrtekPaymaster verifies the signature in validatePaymasterUserOp. Works
on any chain you give it addresses for — anvil, Sepolia, real L2s. Users
never need ETH to make their first move. See paymaster-server/.
3. M-of-N social recovery
The SCA carries a setGuardians(address[], threshold) slot. Recovery is a
single recoverOwner(newOwner, deadline, signatures[]) call that verifies M
unique guardian sigs against a per-account replay nonce. Lose your password,
collect signatures from your friends, rotate to a fresh owner key — same SCA
address. See contracts/src/KrtekSCA.sol,
web/src/routes/Recover.tsx.
4. Phone 2FA via WebSocket relay
The SCA's validateUserOp accepts a 130-byte signature: ownerSig
(EIP-191) || phoneSig (raw secp over the userOpHash). With
lockToPhone=true, every UserOp must be co-signed by a paired phone.
Pairing flow lives in Settings → Phone 2FA; the existing mobile/
companion handles the user-side approval UX. See
web/src/lib/relay/, mobile/.
5. Sourcify APIv2 deep integration
Built specifically for the Sourcify bounty:
- Provenance Card — animated visualization of the source-files →
metadata.json → IPFS CID → CBOR auxdata → on-chain bytecode chain - Transformations diff — renders the
transformations[]array as
bullets and annotated hex showing constructor args / libraries /
immutables / cborAuxdata regions in the deployed bytecode - Multi-chain trust strip —
/v2/contract/all-chains/{address}
showing where else the same code is verified - In-browser re-verification — applies
transformations[]to
recompiledBytecodelocally, decodes the CBOR auxdata, attempts to
reproduce the IPFS CID — proves the verification mathematically without
trusting the public Sourcify server - Source files drawer — every source file with a Solidity highlighter,
the file containing the called function highlighted
Uses APIv2 (the legacy /files/... endpoints went into brownouts in May
2026), the new exact_match / match vocabulary, and proxyResolution
to follow proxies natively. See web/src/lib/sourcify.ts,
web/src/lib/sourcify-verify.ts,
web/src/components/wallet/{ProvenanceCard,TransformationsView,SourceFilesDrawer,MultiChainStrip}.tsx.
6. Multi-profile + auto-resume
Multiple wallets per device under different handles. Pairing state and SCA
caches persist per profile; logging in re-attaches the relay session
transparently. See web/src/lib/profiles.ts.
7. USB Armory MK II — hardware-attested 2FA
Same SCA cosigner slot as the phone, different transport: an i.MX6ULL
Trusted Applet (Rust, no_std, ARM TrustZone Secure World) holds a
secp256k1 key derived from the chip's DCP hardware-attestation primitive
(sk = sha256("krtek-signer-v1" || RPC.Attest)). The applet only
exposes GetPubkey, GetAddress, Approve(digest) and Health — it
has no ExportSecret method, so the key never crosses the syscall
boundary back to Normal World. Pulling the SD card and cloning storage
doesn't yield the key; the DCP secret is silicon-locked.
End-to-end: web app → armory-bridge/ (Bun + Hono on :4141) →
nc 10.0.0.1:4000 (USB-CDC-ECM bridge) → applet → 65-byte recoverable
ECDSA signature → web concatenates ownerSig || armorySig into the
same 130-byte UserOp signature shape the phone path produces. The SCA
verifies with one ECDSA.recover call per signature; it doesn't care
whether the cosigner is a phone or an Armory.
web/src/lib/send.ts runs decideCosigner(sender): if the Armory's
deterministic address matches the on-chain phoneSigner, sign via the
Armory; else if the relay-paired phone matches, sign via the phone; else
owner-only (which the contract refuses if lockToPhone=true). The
applet itself lives in the gitignored gotee_starter/ SDK fork; the
host-side wiring is armory-bridge/,
web/src/lib/armory/, web/src/components/wallet/ArmoryTfaCard.tsx.
8. Cosmic Backup — cTRNG-seeded self-recovery phrase
A 24-word BIP-39 phrase
Challenges we ran into
We had some issues setting up armory hardware device from space computer but we were able to make it work on one of the laptops.
Tracks Applied (6)
Ethereum Core
Future Society
SpaceComputer Bounty
SpaceComputer
Sourcify Bounty
Sourcify
Best ENS Integration for AI Agents
ENS
Apify Bounty
Apify
Technologies used
Cheer Project
Cheering for a project means supporting a project you like with as little as 0.0025 ETH. Right now, you can Cheer using ETH on Arbitrum, Optimism and Base.
