mirror of https://github.com/status-im/EIPs.git
140 lines
6.4 KiB
Markdown
140 lines
6.4 KiB
Markdown
---
|
|
eip: 1102
|
|
title: Opt-in provider access
|
|
author: Paul Bouchon <mail@bitpshr.net>
|
|
discussions-to: https://ethereum-magicians.org/t/eip-1102-opt-in-provider-access/414
|
|
status: Draft
|
|
type: Standards Track
|
|
category: Interface
|
|
created: 2018-05-04
|
|
---
|
|
|
|
## Simple summary
|
|
|
|
This proposal describes a way for DOM environments to expose an Ethereum provider that requires user approval.
|
|
|
|
## Abstract
|
|
|
|
The previous generation of Ethereum-enabled DOM environments follows a pattern of injecting a fully-enabled provider into the DOM without user consent. This puts users of such environments at risk because malicious websites can use this provider to view account information and to arbitrarily initiate unwanted Ethereum transactions on a user's behalf.
|
|
|
|
This proposal outlines a protocol in which DOM environments expose a read-only provider until full provider access is approved by the user.
|
|
|
|
## Specification
|
|
|
|
### Definitions
|
|
|
|
1. **Read-only provider**
|
|
|
|
A read-only provider has no populated accounts and any RPC request that requires an account will fail.
|
|
|
|
2. **Full provider**
|
|
|
|
A full provider has populated accounts and any RPC request that requires an account will succeed.
|
|
|
|
3. **`Provider#enable`**
|
|
|
|
Providers exposed by DOM environments define a new `enable` method that returns a Promise. Calling this method triggers a user interface that allows the user to approve or deny full provider access for a given dapp. The returned Promise is resolved if the user approves full provider access or rejected if the user denies full provider access.
|
|
|
|
```js
|
|
ethereum.enable(): Promise<any>
|
|
```
|
|
|
|
### Protocol
|
|
|
|
DOM environments expose a read-only provider globally at `window.ethereum` by default. Before initiating any RPC request that requires an account, like `eth_sendTransaction`, dapps must request a full provider by calling a new provider method, `ethereum.enable()`. This method triggers a user interface that allows the user to approve or deny full provider access for a given dapp. If the user approves full provider access, the provider at `window.ethereum` is populated with accounts and fully-enabled; if the user denies full provider access, the provider at `window.ethereum` is left unchanged.
|
|
|
|
#### Typical dapp initialization
|
|
|
|
```
|
|
START dapp
|
|
IF web3 is defined
|
|
CONTINUE dapp
|
|
IF web3 is undefined
|
|
STOP dapp
|
|
```
|
|
|
|
#### Proposed dapp initialization
|
|
|
|
```
|
|
START dapp
|
|
IF provider is defined
|
|
ENABLE[1] full provider
|
|
IF user approves
|
|
RESOLVE[2] full provider
|
|
CONTINUE dapp
|
|
IF user denies
|
|
REJECT[3] with error
|
|
STOP dapp
|
|
IF provider is undefined
|
|
STOP dapp
|
|
```
|
|
|
|
##### `[1] ENABLE`
|
|
|
|
Dapps MUST request a full provider by calling the `enable` method on the default read-only provider. This method MUST trigger a user interface that allows the user to approve or deny full provider access for a given dapp. This method MUST return a Promise that is resolved with an array of the user's public addresses if the user approves full provider access or rejected if the user denies full provider access.
|
|
|
|
##### `[2] RESOLVE`
|
|
|
|
If a user approves full provider access, DOM environments MUST expose a fully-enabled provider at `window.ethereum` that is populated with accounts. The Promise returned when calling the `enable` method MUST be resolved with an array of the user's public addresses.
|
|
|
|
##### `[3] REJECT`
|
|
|
|
If a user denies full provider access, the Promise returned when calling the `enable` method MUST be rejected with an informative Error.
|
|
|
|
### Example initialization
|
|
|
|
```js
|
|
window.addEventListener('load', async () => {
|
|
// Read-only provider is exposed by default
|
|
console.log(await ethereum.send('net_version'));
|
|
try {
|
|
// Request full provider if needed
|
|
await ethereum.enable();
|
|
// Full provider exposed
|
|
await ethereum.send('eth_sendTransaction', [/* ... */]);
|
|
} catch (error) {
|
|
// User denied full provider access
|
|
}
|
|
});
|
|
```
|
|
|
|
### Constraints
|
|
|
|
* Browsers MUST expose a read-only provider at `window.ethereum` by default.
|
|
* Browsers MUST NOT expose a full provider globally by default.
|
|
* Dapps MUST request access to a full provider.
|
|
* Users MUST be able to approve or deny full provider access.
|
|
* A full provider MUST be exposed at `window.ethereum` after user approval.
|
|
* Dapps MUST be notified of user approval of full provider access.
|
|
* Dapps MUST be notified of user denial of full provider access.
|
|
|
|
## Rationale
|
|
|
|
The pattern of full provider auto-injection followed by the previous generation of Ethereum-enabled DOM environments fails to protect user privacy and fails to maintain safe user experience: untrusted websites can both view account information and arbitrarily initiate transactions on a user's behalf. Even though most users may reject unsolicited transactions on untrusted websites, a protocol for provider exposure should make such unsolicited requests impossible.
|
|
|
|
This proposal establishes a new pattern wherein dapps must request access to a full Ethereum provider. This protocol directly strengthens user privacy by hiding user accounts and preventing unsolicited transaction requests on untrusted sites.
|
|
|
|
### Immediate value-add
|
|
|
|
* Users can reject full provider access on untrusted sites to hide accounts.
|
|
* Users can reject full provider access on untrusted sites to prevent unsolicited transactions.
|
|
|
|
### Long-term value-add
|
|
|
|
* Dapps could request specific account information based on user consent.
|
|
* Dapps could request specific user information based on user consent (uPort, DIDs).
|
|
* Dapps could request a specific network based on user consent.
|
|
* Dapps could request multiple instances of the above based on user consent.
|
|
|
|
## Backwards compatibility
|
|
|
|
This proposal impacts dapp authors and requires that they request access to a full Ethereum provider before using it to initiate any RPC call that requires an account. This proposal also impacts developers of Ethereum-enabled DOM environments or dapp browsers as these tools should no longer auto-expose a full provider populated with accounts; instead, they should expose a read-only provider and only expose a full provider if a website requests one and a user consents to its access.
|
|
|
|
## Implementation
|
|
|
|
The MetaMask team is currently working an [MVP implementation](https://github.com/MetaMask/metamask-extension/pull/4703) of the strategy described above and expects to begin limited user testing soon.
|
|
|
|
## Copyright
|
|
|
|
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|