-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
EIP-3085: wallet_addEthereumChain (#3085)
Rendered file: https://github.com/rekmarks/EIPs/blob/2016/EIPS/eip-3085.md This PR adds EIP-3085, which introduces the wallet_addEthereumChain RPC method. It's basically EIP-2015, without requiring the network to be switched. I think 2015 is a great idea, but wallets may desire an RPC method that only adds a chain, without requiring that the network is changed. For example, allowing dapps to request network changes is bound to cause UX issues, especially as we see dapps moving to different layer 2 chains.
- Loading branch information
Showing
1 changed file
with
234 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
--- | ||
eip: 3085 | ||
title: Wallet Add Ethereum Chain RPC Method (`wallet_addEthereumChain`) | ||
author: Erik Marks (@rekmarks), Pedro Gomes (@pedrouid) | ||
discussions-to: https://github.com/ethereum/EIPs/issues/3086 | ||
status: Draft | ||
type: Standards Track | ||
category: Interface | ||
created: 2020-11-01 | ||
requires: 155, 695, 3091 | ||
--- | ||
|
||
## Simple Summary | ||
|
||
An RPC method for adding Ethereum chains to wallet applications. | ||
|
||
## Abstract | ||
|
||
The `wallet_addEthereumChain` RPC method allows Ethereum applications ("dapps") to suggest chains to be added to the wallet application. | ||
The caller must specify a chain ID and some chain metadata. | ||
The wallet application may arbitrarily refuse or accept the request. | ||
`null` is returned if the chain was added, and an error otherwise. | ||
|
||
Important cautions for implementers of this method are included in the [Security Considerations](#security-considerations) section. | ||
|
||
## Motivation | ||
|
||
A dapp may require the user to interact with multiple Ethereum chains in order to function. | ||
A may or may not be supported by the user's wallet application. | ||
`wallet_addEthereumChain` enables dapps to request any necessary chains to be added to the user's wallet. | ||
This provides UX benefits for dapps and wallets that want to provide such functionality. | ||
|
||
## Specification | ||
|
||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC-2119](https://www.ietf.org/rfc/rfc2119.txt). | ||
|
||
### `wallet_addEthereumChain` | ||
|
||
The method accepts a single object parameter, with a `chainId` and some chain metadata. | ||
The method returns `null` if the chain was added to the wallet, and an error otherwise. | ||
|
||
The wallet **MAY** reject the request for any reason. | ||
The wallet **MUST** reject the request if the `chainId` is improperly formatted. | ||
The wallet **MUST** reject the request if the wallet does not support the chain with the specified `chainId`. | ||
|
||
> Note that this method makes **no** statement about whether the wallet should change the user's currently selected chain, if the wallet has a concept thereof. | ||
#### Parameters | ||
|
||
`wallet_addEthereumChain` accepts a single object parameter, specified by the following TypeScript interface: | ||
|
||
```typescript | ||
interface AddEthereumChainParameter { | ||
chainId: string; | ||
blockExplorerUrl?: string; | ||
chainName?: string; | ||
nativeCurrency?: { | ||
name: string; | ||
symbol: string; | ||
decimals: number; | ||
}; | ||
rpcUrl?: string; | ||
} | ||
``` | ||
|
||
Only the `chainId` is required per this specification, but a wallet **MAY** require any other fields listed, and impose additional requirements on them. | ||
|
||
- `chainId` | ||
- **MUST** specify the integer ID of the chain as a hexadecimal string, per the [`eth_chainId`](./eip-695.md) Ethereum RPC method. | ||
- The wallet **SHOULD** compare the specified `chainId` value with the `eth_chainId` return value from the endpoint. | ||
If these values are not identical, the wallet **MUST** reject the request. | ||
- `blockExplorerUrl` | ||
- If provided, **MUST** specify the URL of a block explorer web site for the chain. | ||
- The block explorer API routes **SHOULD** be compatible with [EIP-3091](./eip-3091.md). | ||
- `chainName` | ||
- If provided, **MUST** specify a human-readable name for the chain. | ||
- `nativeCurrency` | ||
- If provided, **MUST** describe the native currency of the chain using the `name`, `symbol`, and `decimals` fields. | ||
- `rpcUrl` | ||
- If provided, **MUST** specify the URL of the RPC endpoint used to communicate with the chain. | ||
|
||
All URL string fields **MUST** include the protocol component of the URL. | ||
HTTPS **SHOULD** be used. | ||
|
||
#### Returns | ||
|
||
The method **MUST** return `null` if the request was successful, and an error otherwise. | ||
|
||
If a chain with the provided parameters was already added, the request is considered successful, and the method **MUST** return `null`. | ||
|
||
The wallet **SHOULD NOT** allow the same `chainId` to be added multiple times. | ||
See [Security Considerations](#security-considerations) for more information. | ||
|
||
### Examples | ||
|
||
These examples use JSON-RPC, but the method could be implemented using other RPC protocols. | ||
|
||
To add the Goerli test chain: | ||
|
||
```json | ||
{ | ||
"id": 1, | ||
"jsonrpc": "2.0", | ||
"method": "wallet_addEthereumChain", | ||
"params": [ | ||
{ | ||
"chainId": "0x5", | ||
"chainName": "Goerli", | ||
"rpcUrl": "https://goerli.infura.io/v3/INSERT_API_KEY_HERE", | ||
"nativeCurrency": { | ||
"name": "Goerli ETH", | ||
"symbol": "gorETH", | ||
"decimals": 18 | ||
}, | ||
"blockExplorerUrl": "https://goerli.etherscan.io" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
To add POA Network's xDAI chain: | ||
|
||
```json | ||
{ | ||
"id": 1, | ||
"jsonrpc": "2.0", | ||
"method": "wallet_addEthereumChain", | ||
"params": [ | ||
{ | ||
"chainId": "0x64", | ||
"chainName": "xDAI Chain", | ||
"rpcUrl": "https://dai.poa.network", | ||
"nativeCurrency": { | ||
"name": "xDAI", | ||
"symbol": "xDAI", | ||
"decimals": 18 | ||
} | ||
} | ||
] | ||
} | ||
``` | ||
|
||
A success response: | ||
|
||
```json | ||
{ | ||
"id": 1, | ||
"jsonrpc": "2.0", | ||
"result": null | ||
} | ||
``` | ||
|
||
A failure response: | ||
|
||
```json | ||
{ | ||
"id": 1, | ||
"jsonrpc": "2.0", | ||
"error": { | ||
"code": 4001, | ||
"message": "The user rejected the request." | ||
} | ||
} | ||
``` | ||
|
||
## Rationale | ||
|
||
The design of `wallet_addEthereumChain` is deliberately ignorant of what it means to "add" a chain to a wallet. | ||
The meaning of "adding" a chain to a wallet depends on the wallet implementation. | ||
Ultimately, neither the user nor the dapp can now whether adding the chain "worked" until they have successfully interacted with it. | ||
|
||
When calling the method, specifying the `chainId` will always be necessary, since in the universe of Ethereum chains, the [EIP-155](./eip-155.md) chain ID is effectively the GUID of a chain. | ||
The remaining parameters amount to what, in the estimation of authors, a wallet will minimally require in order to effectively support a chain and accurately represent it to the user. | ||
The network ID (per the `net_version` RPC method) was omitted since it is effectively superseded by the chain ID. | ||
|
||
For [security reasons](#security-considerations), a wallet should always attempt to validate the chain metadata provided by the dapp, and may choose to fetch the metadata elsewhere entirely. | ||
Either way, there's no way to know what the wallet will _need_ with respect to the chain metadata. | ||
Therefore, all parameters except `chainId` are listed as optional, even though a wallet may require them in practice. | ||
|
||
This specification does not mandate that the wallet "switches" its active chain, if the result is successful. | ||
|
||
For related work, see [EIP-2015](./eip-2015.md). | ||
|
||
## Security Considerations | ||
|
||
`wallet_addEthereumChain` is a powerful method that exposes the end user to serious risks if implemented incorrectly. | ||
Most of these risks can be avoided by validating the request data in the wallet, and clearly disambiguating different chains in the wallet UI. | ||
|
||
### Chain IDs | ||
|
||
Since the chain ID used for signing determines which chain a transaction is valid for, handling the chain ID correctly is of utmost importance. | ||
The wallet should: | ||
|
||
- Ensure that a submitted chain ID is valid. | ||
- It should be submitted as a `0x`-prefixed hexadecimal string per [EIP-695](./eip-695.md), and parse to an integer number. | ||
- Prevent the same chain ID from being added multiple times, for example with different RPC URLs. | ||
- Only use the submitted chain ID to sign transactions, **never** a chain ID received from an RPC endpoint. | ||
- A malicious or faulty endpoint could return arbitrary chain IDs, and potentially cause the user to sign transactions for unintended chains. | ||
- Verify that the specified chain ID matches the return value of `eth_chainId` from the endpoint, as described in [this specification](#parameters). | ||
|
||
### RPC Endpoints | ||
|
||
Wallets generally interact with chains via an RPC endpoint, identified by some URL. | ||
Most wallets ship with a set of chains and corresponding trusted RPC endpoints. | ||
The endpoints identified by the `rpcUrl` parameter cannot be assumed to be honest or even correct. | ||
Moreover, even trusted endpoints endpoints can expose users to privacy risks depending on their data collection practices. | ||
|
||
Therefore, the wallet should: | ||
|
||
- Inform users that their on-chain activity and IP address will be exposed to the endpoint. | ||
- If the endpoint is unknown to the wallet, inform users that the endpoint may behave in unexpected ways. | ||
- Observe good web security practices when interacting with the endpoint, such as require HTTPS. | ||
|
||
### UX | ||
|
||
Adding a new chain to the wallet can have significant implications for the functionality of the wallet and the experience of the user. | ||
A chain should never be added without the explicit consent of the user, and different chains should be clearly differentiated in the wallet UI. | ||
In service of these goals, the wallet should: | ||
|
||
- When receiving a `wallet_addEthereumChain` request, display a user confirmation informing the user that a specific dapp has requested that the chain be added. | ||
- The confirmation used in [EIP-1102](./eip-1102.md) may serve as a point of reference. | ||
- Ensure that any chain metadata, such as `nativeCurrency` and `blockExplorerUrl`, are validated and used to maximum effect in the UI. | ||
- If the wallet UI has a concept of a "currently selected" or "currently active" chain, ensure that the user understands when a chain added using `wallet_addEthereumChain` becomes selected. | ||
|
||
### Validating Chain Data | ||
|
||
A wallet that implements `wallet_addEthereumChain` should expect to encounter requests for chains completely unknown to the wallet maintainers. | ||
That said, community resources exist that can be leveraged to verify requests for many Ethereum chains. | ||
The wallet should maintain a list of known chains, and verify requests add chains against that list. | ||
Indeed, unless there are good reasons not to, the wallet should _prefer its own chain metadata_ over anything submitted with a `wallet_addEthereumChain` request. | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |