As part of my work on MetaMask, I helped create an industry-wide standard to improve Ethereum’s privacy layer.
What.. is an Ethereum browser?
Ethereum browsers & extensions let users interact
with decentralized applications, or “dapps” — websites that involve a smart
contract as part (or all) of their backend. Although dapps mostly look like
regular websites, they have a wild side: occasionally they’ll call a smart
contract function, or ask their users to send some ETH.
These interactions expect users to be able to cryptographically sign messages or
transactions with their private keys. But there is no standardized browser API for
“ask the user to sign this transaction” like there is for “tell me where the nice lady’s mouse is”
or “let me know if this person’s window is too small.”
That’s where Ethereum browsers come in: MetaMask runs as a browser extension and helps
the user get set up with a set of Ethereum addresses & corresponding private keys.
The extension then exposes an API to websites to let them suggest actions to the user,
and voila: the dapp can now ask the user to sign the transaction it needs.
Before our work on this privacy standard, Ethereum browsers had a sort of shotgun strategy.
On any page the user visited, the extension injected a web3 object
into the global page context and exposed the Ethereum provider API.
The web3 object contains a number of convenience methods
along with the user’s Ethereum address. The Ethereum provider allows for sites
to make RPC calls directly to Infura, which MetaMask uses to submit transactions
to the blockchain. This was super helpful for adoption and development. Dapps
simply looked for the proper APIs and either found them (yay) or didn’t (go download MetaMask, silly!)
So what's the issue?
There's a glaring privacy issue in the pattern described above. Using the internet with MetaMask
installed meant exposing your Ethereum address to every site you visited,
dapp or not. Coupled with the fact that all blockchain data is public, it’s
easy to imagine how this data could be used to track, fingerprint, or phish unsuspecting users.
We drafted EIP 1102 [link] to propose a new standard: rather than exposing
addresses by default, dapps should ask permission from the user to see their
address. The idea is simple, but it changes the fundamental assumptions dapps
can make, causing a breaking change for every dapp and browser in the ecosystem.
Advocating for and implementing the change ran the risk of fragmenting or
frustrating the Ethereum dev community, but we considered the change a necessity for safe broad adoption.
Boiling the ocean
First, we rallied support from other Ethereum browser teams. The ecosystem
values interoperability and is unusually collaborative. Each team is invested
in supporting the development and accessibility of dapps, and un-even implementation
of a new standard could lead to confusion and fragmentation. Teams at Status,
Mist, imToken, and Coinbase Wallet were supportive of the idea, and after
several conversations, they agreed to implement the standard on a similar timeline to ours.
We published a series of blog posts and discussion threads to inform the
Ethereum developer community. The EIP itself had already undergone extensive
discussion, but the community of folks who would need to update their
applications is different from the standards geeks who were involved in its initial ratification.
Feedback is a gift
This is where it got interesting. Some developers were particularly concerned
with how this change would affect their apps first-time flows. The first
version of the proposal removed all visible presence of an Ethereum browser
altogether, and required dapps to use the postMessage API. If the
application got a response, it was good to go – but if the app did not
receive a response, it was impossible to distinguish between users who
declined to share their address and users who had no Ethereum browser/add-on
installed. In a world where onboarding is already a massive deterrent, this
change — despite its noble intentions — was met with resistance.
The proposal was initially drafted this way to ensure complete privacy
for the end-user. But it became clear as developer feedback poured in
that complete user privacy was less important than establishing an ecosystem
that was user-friendly in its basic primitives. We don't want to make onboarding
such a burden that there are no users to protect in the first place!
We eventually drafted a revised version of the proposal that exposes a simple
object to all webpages by default. Before this standard, this object (called the
Ethereum "provider") exposed a whole suite of convenience methods. The revised proposal
whittled those methods down to one: ethereum.enable(). Calling .enable() would
prompt the user to disclose their Ethereum address to the site they're visiting,
and business continues as usual.
The revised proposal doesn't achieve complete privacy: it's possible for any site to
know whether their user has an Etheruem browser add-on installed by detecting the presence
of the provider object. But it's still a substantial step in favor of user privacay without
harming UX across the nascent dapp ecosystem.
Go Time.
After announcing the standard, accepting feedback and making changes, reaching out
to literally hundreds of dapps and dapp browsers, we launched this feature in mid-November
and cheered as the ecosystem updated in line with the spec.
But there's one last step. Today, all new downloads of MetaMask ship with "Privacy Mode" as an
optional feature that users can enable in their settings. We're in the process of giving stray
applications a several-month "grace period" to update before enabling by default for all users.
This was my first experience with standards work, and, while it took a much longer development cycle
than what I'm used to, the basic principles are similar to other product development: understand your
users & their needs, explore the solution space & gather feedback, develop & launch carefully
and iterate on the outcome. Thanks for reading!