原标题:What I would love to see in a wallet
Author: Vitalik, founder of Ethereum; Translator: Deng Tong, Golden Finance
Special thanks to Liraz Siri, Yoav Weiss, and the ImToken, Metamask, and OKX developers for their feedback and review.
A critical layer of the Ethereum infrastructure stack, but one that is often underestimated by core L1 researchers and developers, is the wallet. The wallet is the window between the user and the Ethereum world, and the user can only benefit from any decentralization, censorship resistance, security, privacy, or other properties provided by Ethereum and its applications if the wallet itself also possesses these properties.
Recently, we've seen a lot of progress in Ethereum wallets to improve UX, security, and functionality. The purpose of this post is to give my own take on some of the features an ideal Ethereum wallet should have. This is not a complete list; it reflects my cypherpunk tendencies, it focuses on security and privacy, and it's almost certainly incomplete in terms of UX. However, I think wish lists are less effective in optimizing UX than simply deploying and iterating based on feedback, so I think focusing on security and privacy properties is the most valuable.
User experience for cross-L2 transactions
There is an increasingly detailed roadmap for improving the user experience across L2, and that roadmap has both a short-term and a long-term part. Here I’ll talk about the short-term part: ideas that are theoretically implementable even today.
The core idea is (i) built-in cross-L2 sends, and (ii) chain-specific addresses and payment requests. Your wallet should be able to provide you with an address (following the style of this ERC draft) that looks like this:
0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045@optimism.eth
When someone (or some application) gives you an address in this format, you should be able to paste it into the "To" field of your wallet and click "Send". The wallet should automatically handle the sent data in any way possible:
If you already have enough tokens of the required type on the target chain, send the tokens directly;
If you have a token of the type you need on another chain (or multiple other chains), use a protocol like ERC-7683 (effectively a cross-chain DEX) to send the token;
If you have different types of tokens on the same chain or other chains, use a decentralized exchange to convert them to the correct type of token on the correct chain and send them. This should require explicit permission from the user: the user will see how much they paid in fees, and how much the recipient received in fees.
A mockup of a possible wallet interface with cross-chain address support
The above applies to the use case of “you copy-paste an address (or ENS, e.g. vitalik.eth@optimism.eth) so that someone pays you”. If a dapp requests a deposit (e.g. see the Polymarket example), then the ideal flow would be to extend the web3 API and allow the dapp to make a chain-specific payment request. Your wallet would then be able to fulfill that request in whatever way it needs to. For the user experience to be good, getAvailableBalance requests would also need to be standardized, and wallets would need to think carefully about which chains to store user assets on by default to maximize security and ease of transfer.
Chain-specific payment requests can also be put into a QR code, which can be scanned by mobile wallets. In an in-person (or online) consumer payment scenario, the recipient would issue a QR code or web3 API call saying “I want X units of token Y on chain Z, with reference ID or callback W”, and the wallet would be free to fulfill that request in any way possible. Another option is a claim chaining protocol, where the user’s wallet generates a QR code or URL containing authorization to claim a certain amount of funds from their on-chain contract, and it’s the recipient’s job to figure out how to transfer those funds to their account.
Another related topic is Gas payments. If you receive assets on an L2 that doesn't have ETH yet, and need to send a transaction on that L2, the wallet should be able to automatically use a protocol (such as RIP-7755) to pay for Gas on the chain where you have ETH. If the wallet wants you to do more transactions on L2 in the future, it should also only use a DEX to send ETH worth millions of Gas so that future transactions can spend Gas directly there (because it's cheaper that way).
Account Security
One way I conceptualize the account security challenge is that a good wallet should serve two purposes simultaneously: (i) protecting users from hacks or malicious attacks by wallet developers, and (ii) protecting users from their own mistakes.
The "error" on the left was unintentional. However, when I saw it, I realized it fit the context very well, so I decided to keep it.
For over a decade, my preferred solution has been social recovery and multi-signature wallets with hierarchical access control. A user's account has two layers of keys: a master key and N guardians (e.g. N = 5). The master key is capable of low-value and non-financial operations. Most guardians need to perform (i) high-value operations, such as sending the full value of an account, or (ii) changing the master key or any guardian. If desired, the master key can be allowed to perform high-value operations via a time lock.
The above is a basic design that can be expanded. Permission mechanisms such as session keys and ERC-7715 can help support different balances between convenience and security for different applications. More complex guardian architectures, such as having multiple time lock durations at different thresholds, can help maximize the chances of successfully recovering legitimate accounts while minimizing the risk of theft.
Who or what should the guardian be?
For experienced crypto users in a community of experienced cryptocurrency users, a viable option is the keys of your friends and family. If you ask each person to provide you with a new address, then no one needs to know who they are — in fact, your guardians don’t even need to know who each other is. If they haven’t tipped you off, the chances of them colluding are slim. However, for most new users, this option is not available.
The second option is institutional guardians: companies that specialize in providing services that will only sign a transaction if they get additional confirmation from your request. A confirmation code, or for high-value users a video call. People have been trying to make these things for a long time. I covered CryptoCorp in 2013. However, so far, these types of companies have not been very successful.
The third option is multiple personal devices (e.g. mobile, desktop, hardware wallet). This is feasible, but can also be difficult to set up and manage for inexperienced users. There is also the risk of devices being lost or stolen, especially if they are in the same location.
Lately, we've started seeing more and more key-based wallets. Keys can only be backed up on your device, making them a personal device solution, or in the cloud, making their security dependent on a complex mix of assumptions about password security, institutions, and trusted hardware. In practice, keys are a valuable security gain for the average user, but they are not sufficient on their own to protect a user's life savings.
Fortunately, with ZK-SNARKs, we have a fourth option: ZK-wrapped centralized IDs. This type includes zk-email, Anon Aadhaar, Myna Wallet, etc. Basically, you can take a centralized ID in many forms (corporate or government) and convert it into an Ethereum address, and you can only send transactions by generating a ZK-SNARK that proves that you have the centralized ID.
With this addition, we now have a wide range of choices and the unique “newbie-friendliness” of ZK-wrapped centralized IDs.
To do this, it needs to be done through a simplified and integrated UI: you should be able to just specify that you want "example@gmail.com" as a guardian, and it should automatically generate the corresponding zk-email Ethereum address under the hood. Advanced users should be able to enter their email (and perhaps a privacy salt saved in that email) into an open source third-party application and confirm that the generated address is correct. The same should be true for any other supported guardian type.
Possible security interface models
Note that a practical challenge with zk-email today is that it relies on DKIM signatures, which use keys that are rotated every few months, and which themselves are not signed by any other authority. This means that zk-email today has some level of trust requirement beyond the provider itself; this could be reduced if zk-email used TLSNotary inside trusted hardware to verify updated keys, but this is not ideal. Hopefully, email providers will start signing their DKIM keys directly. Today, I recommend zk-email to one guardian, but not to most: do not store funds in a setup where a broken zk-email means you can’t access your funds.
New Users and In-App Wallet
New users don’t really want to enter a ton of guardians in their first signup experience. So wallets should offer them a very simple option. A natural path would be to do a 2-of-3 selection using zk-email on their email address, a key stored locally on the user’s device (perhaps a master key), and a backup key held by the provider. As users become more experienced or accumulate more assets, at some point they should be prompted to add more guardians.
Wallet integration into apps is inevitable, as apps trying to attract non-crypto users don’t want users to download two new apps at once (the app itself, plus an Ethereum wallet) which creates a cluttered user experience. However, users of many app wallets should be able to link all of their wallets together so they only have to worry about one “access control problem”. The simplest way to do this is with a tiered approach, where there is a quick “linking” process that allows users to set their main wallet as the guardian for all of their in-app wallets. The Farcaster client Warpcast already supports this:
By default, the recovery for your Warpcast account is controlled by the Warpcast team. However, you can "take over" your Farcaster account and change the recovery to your own address.
Protect users from scams and other external threats
Beyond account security, today's wallets do a lot to identify fake addresses, phishing, scams, and other external threats, and do their best to protect users from such threats. At the same time, many countermeasures are still fairly primitive: for example, requiring a click to send ETH or other tokens to any new address, regardless of whether you're sending $100 or $100,000. There's no single silver bullet here. It's a slow, ongoing series of fixes and improvements for different classes of threats. However, there's a lot of value in continuing to work on improvements here.
privacy
It’s time to start taking privacy on Ethereum more seriously. ZK-SNARK technology is now advanced enough, privacy technologies that don’t rely on backdoors to reduce regulatory risk (such as privacy pools) are becoming more mature, and secondary infrastructure like Waku and ERC-4337 mempools are slowly becoming more stable. However, until now, making private transfers on Ethereum required users to explicitly download and use a “privacy wallet” like Railway (or Umbra for stealth addresses). This adds a huge inconvenience and reduces the number of people willing to make private transfers. The solution is that private transfers need to be integrated directly into wallets.
A simple implementation is as follows. The wallet can store part of the user's assets as a "private balance" in the privacy pool. When the user transfers money, it will automatically exit the privacy pool first. If the user needs to receive funds, the wallet can automatically generate a stealth address.
Additionally, the wallet can automatically generate a new address for each application the user participates in (e.g., a defi protocol). Deposits will come from the privacy pool and withdrawals will go directly into the privacy pool. This allows a user's activity in any one application to be unlinked from their activity in other applications.
One of the advantages of this technology is that it is a natural path not only for privacy-preserving asset transfers, but also for privacy-preserving identity. Identity already happens on-chain: any application gated with identity proofs (e.g. Gitcoin Grants), any token-gated chat, the Ethereum Follow protocol, and so on are all on-chain identities. We want this ecosystem to be privacy-preserving as well. This means that a user’s on-chain activity should not be collected in one place: each project should be stored separately, and a user’s wallet should be the only thing with a “global view” that sees all of your proofs at once. A native multi-account-per-user ecosystem helps achieve this, as do off-chain proof protocols like EAS and Zupass.
This represents a pragmatic vision for privacy on Ethereum in the medium term. It is achievable today, although some features could be introduced at L1 and L2 to make privacy-preserving transfers more efficient and reliable. Some privacy advocates argue that the only acceptable thing is complete privacy for everything: encrypting the entire EVM. I think this is probably the ideal long-term outcome, but it requires a more fundamental rethinking of the programming model, and it is not yet at a level of maturity that is ready for deployment on Ethereum. We do need privacy by default to get a sufficiently large anonymity set. However, focusing first on (i) transfers between accounts, and (ii) identity and identity-related use cases (e.g. private proofs) is a pragmatic first step that is easier to implement, and wallets can start using today.
Ethereum wallets also need to be data wallets
One consequence of any effective privacy solution, whether for payments, identity, or other use cases, is that it creates a need for users to store data off-chain. This is evident in Tornado Cash, which requires users to keep “notes” that represent deposits of 0.1-100 ETH each. More modern privacy protocols sometimes keep encrypted data on-chain and decrypt it using a single private key. This is risky because if the key is compromised, or quantum computers become feasible, the data becomes public. The need for off-chain data storage is even more evident in off-chain proofs such as EAS and Zupass.
Wallets need to be software that not only stores on-chain access permissions, but also stores your private data. The non-crypto world is increasingly recognizing this, e.g. see Tim Berners-Lee’s recent work on personal data storage. All the problems we need to solve around robust access control, we also need to solve around robust accessibility and non-leakage of data. Perhaps these solutions can be stacked together: if you have N guardians, use M-of-N secret sharing between those N guardians to store your data. The data is inherently harder to protect because you can’t revoke someone’s share of the data, but we should come up with decentralized custody solutions that are as secure as possible.
Security chain access
Today, wallets trust their RPC providers to tell them anything about the chain. This is a vulnerability in two ways:
RPC providers may try to steal money by providing them with false information, such as about market prices.
RPC providers can extract private information about the applications and other accounts that the user is interacting with
Ideally, we want to close both of these loopholes. To solve the first problem, we need standardized light clients for L1 and L2 that can directly verify blockchain consensus. Helios already does this for L1, and has been doing some preliminary work to support some specific L2s. In order to properly cover all L2s, we need a standard by which a configuration contract representing an L2 (also for chain-specific addresses) can declare a function, perhaps in a manner similar to ERC-3668, that contains fetching the most recent state roots and proving and receipts against those state roots. This way we can have a universal light client that allows wallets to securely verify any state or event on L1 and L2.
For privacy, the only realistic approach today is to run your own full node. However, now that L2 is coming into the picture, it is becoming increasingly difficult to run a full node for everything. The equivalent of a light client here is Private Information Retrieval (PIR). PIR involves a server that keeps a copy of all the data and a client that sends an encrypted request to the server. The server performs computations on all the data and returns the data the client needs, encrypted to the client's key, without revealing to the server which piece of data the client accessed.
To keep the servers honest, the individual database items are themselves Merkle branches, so clients can verify them using a light client.
PIR is computationally expensive. There are several ways to solve this problem:
Brute force: Improvements in algorithms or specialized hardware might make PIR run fast enough. These techniques may depend on preprocessing: the server could store encrypted and scrambled data for each client, and the clients could query that data. The main challenge in the Ethereum environment is adapting these techniques to rapidly changing datasets (like countries). This makes real-time computation cheaper, but will likely make total computation and storage costs higher.
Weakens privacy requirements: for example, there can only be 1 million "mixins" per lookup, so the server knows about a million possible values that the client can access, but not any finer granularity.
Multi-server PIR: The PIR algorithm is generally faster if you use multiple servers and the honesty between these servers is assumed to be 1-of-N.
Anonymity rather than confidentiality: Requests can be sent through the mixnet, hiding the sender of the request, rather than hiding the content of the request. However, doing so effectively inevitably increases latency, thus worsening the user experience.
Figuring out the right combination of techniques to maximize privacy while maintaining practicality in the Ethereum context is an open research problem, and I welcome cryptographers to try to do so.
Ideal Keystore Wallet
In addition to transfers and state access, another important workflow that needs to work smoothly in a cross-L2 context is changing the verification configuration of an account: whether it is changing its keys (such as recovery), or making deeper changes to the entire logic of the account. There are three tiers of solutions here, arranged in order of increasing difficulty:
Replay updates: When a user changes their configuration, the message authorizing this change will be replayed on every chain where the wallet detects that the user owns assets. Potentially, the message format and validation rules can be chain-independent and therefore automatically replayed on as many chains as possible.
Keystore on L1: The configuration information is located on L1, and the wallet on L2 uses L1SLOAD or REMOTESTATICCALL to read it. In this way, you only need to update the configuration on L1, and the configuration will take effect automatically.
Keystore on L2: Configuration information exists on L2, and wallets on L2 read it using ZK-SNARKs. This is the same as (2), except that the keystore may be cheaper to update, but on the other hand more expensive to read.
Solution (3) is particularly powerful because it combines well with privacy. In a normal "privacy solution", the user has a secret s, a "leaf value" L is published on-chain, and the user proves that L = hash(s, 1) and N = hash(s, 2) for some (never revealed) secret they control. An invalidator N is published that ensures that future spends of the same leaf fail without revealing L. This depends on the user keeping s safe. A recovery-friendly privacy solution would say: s is a location on-chain (e.g. an address and storage slot), and the user must prove for a state query: L = hash(sload(s), 1) .
Dapp Security
The weakest link in user security is often the dapp. Most of the time, users interact with applications by visiting a website, which implicitly downloads the user interface code from a server in real time and then executes it in the browser. If the server is hacked, or the DNS is hacked, the user will get a fake copy of the interface, which can trick the user into performing arbitrary actions. Wallet features such as transaction simulation are very helpful in reducing risk, but they are far from perfect.
Ideally, we will move the ecosystem to on-chain content versioning: users will access dapps by their ENS name, which will contain the IPFS hash of the interface. Updating the interface requires an on-chain transaction from a multisig or DAO. Wallets will show users if they are interacting with a more secure on-chain interface or a less secure Web2 interface. Wallets can also show users if they are interacting with a secure chain (e.g. Phase 1+, multi-security audited).
For privacy-conscious users, the wallet can also add a paranoid mode that requires users to click to accept HTTP requests, not just web3 operations:
Possible interface models for paranoid mode
A more advanced approach would be to go beyond HTML+Javascript and write the business logic of the dapp in a dedicated language (perhaps a relatively thin overlay on Solidity or Vyper). The browser can then automatically generate a UI for any desired functionality. OKContract is already doing this.
Another direction is crypto-economic information defense: dapp developers, security firms, chain deployers, and others can set up a bond that will be paid to affected users if a dapp is hacked or harms users in a highly misleading way. Adjudicated by some on-chain DAO. Wallets can display scores based on the size of the bond to users.
The Longer Future
The above is all in the context of traditional interfaces that involve pointing and clicking things and typing things into text fields. However, we are also on the cusp of a more profound change in paradigm:
Artificial intelligence, which could lead us away from a point-and-click typing paradigm to a “say what you want to do and the robot will figure it out” paradigm;
brain-computer interfaces, ranging from “gentle” methods like eye tracking to more direct and even invasive techniques (see: the first Neuralink patient this year);
Client-side active defense: Brave browser actively protects users from ads, trackers, and many other bad actors. Many browsers, plugins, and crypto wallets have entire teams actively working to protect users from a variety of security and privacy threats. These “active guardians” will only get stronger over the next decade.
Together, these three trends will lead to a deeper rethinking of how interfaces work. Through natural language input, eye tracking, or eventually more direct brain-computer interfaces, coupled with your history (perhaps including text messages, as long as all data is processed locally), the "wallet" can have a clear and intuitive understanding of what you want to do. The AI can then translate this intuition into a specific "action plan": a series of on-chain and off-chain interactions to accomplish what you want. This can greatly reduce the need for third-party user interfaces. If the user does interact with a third-party application (or other users), the AI should think adversarially on the user's behalf, identifying any threats and proposing an action plan to avoid them. Ideally, there should be an open ecosystem of these AIs, produced by different groups with different biases and incentive structures.
These more radical ideas rely on extremely immature technology today, so I wouldn’t put my assets into a wallet that relies on them today. However, it seems clear that things like this are the future, so it’s worth starting to explore more actively in this direction.