Cross-Connect
Overview
When the provider generates signatures with a key not specifically created for the dapp, it is cross-connected. Cross-connecting keys is required to support certain data portability use cases for web apps.
Cross-connecting keys without restrictions is fundamentally insecure, as it relies on users identifying dangerous signature requests. Some in-page provider implementations use wallet firewalls to mitigate this threat. Firewalls identify malicious signature requests and offer warnings to users.
Wallet firewalls are a welcome addition to the Web3 security landscape, but they have important shortcomings. The firewall’s threat intelligence may be out of date, or it may give a false negative. If the firewall gives too many warnings, users get desensitized, and if it’s too lax, then it's ineffective. Placing the victim under time pressure is common in social attacks, so users are more likely to ignore warnings than normally. Finally, if every new dapp comes with a warning, that discourages experimentation, so even if firewalls reduce harm of phishing, they can hamper the growth of the ecosystem.
While most in-page provider implementations let users cross-connect keys without restrictions, our approach to security is to eliminate attack vectors where we can. Therefore, in cross-connect mode, we reduce the decision the user has to make to sign in, payment approval and spender approval decisions and reject signature requests where we cannot guarantee this. If a signature request is blocked, users are guided to switch to the dapp key to continue. The dapp key is an isolation mechanism that guarantees that a malicious dapp cannot exploit assets that the user explicitly trusted it with.
Use Cases
The following data portability patterns for web apps need cross connect:
Approval Type | Signature Type | Use Case |
---|---|---|
Sign In | Off-chain | - Prove ownership of an address (e.g. SIWE or accept ToS). - Prove ownership of assets (e.g. nf.td and Phi Land). |
Payment Approval | On- or off-chain | - Mint an NFT based on an allow list or holding an asset (e.g. Sunflower Land + Bumpkins, Lens ecosystem). - Supply collateral for a loan. |
Spender Approval | On- or off-chain | - List a game item for sale on an exchange while playing the game (e.g. Sunflower Land). |
Sign In
Internet users are familiar with the concept of signing in to a website with a password or through a social provider. Recently, passwordless logins based on WebAuthn started to take off.
Proving ownership of an address in the Ethereum ecosystem is very similar from a UX perspective to passwordless sign in. Therefore, we present signature approval requests to prove ownership of an address as sign in requests, even if sometimes they are authorization requests from a technical perspective (as opposed to authentication requests).
If the sign in message is not a SIWE message, then the original message is displayed to the user since it might have legal implications (e.g. attesting not to be a U.S. resident on DEXes for compliance reasons).
Payment Approval
Internet users are familiar with making online payments. Payment approval type requests, let that be making a swap, minting an NFT or supplying collateral for a loan, should be as simple as Apple Pay.
If the user receives a standard token in exchange for the payment, the payment is akin to a trade and we display both the spent and received tokens.
Spender Approval
Spender approval is a novel concept introduced by Ethereum. Its purpose is to let decentralized exchanges settle trades based on users' orders. Spender approval must be supported in cross-connect mode, because playing a game using one dapp while trading game items using another dapp is a common usage pattern.
There are two challenges we need to solve in order to provide a secure and smooth experience for spender approvals:
- Since spender approval is a novel concept, we need to make sure that the prompt that we display matches the user's intention while making sure at the same time the user understands the consequences of giving a spender approval.
- We need to keep track of approvals and let users find and revoke them in a way that matches their mental model.
Spender Approval Dialog
In order to solve first challenge, we use a two phase approval dialog:
flowchart TB
spender_approval([Spender approval request from dapp]) --> pledge_token{{Pledge token?}}
pledge_token -- Yes --> allow_spend{{Allow spend until pledge is cancelled?}}
pledge_token -- No --> reject([Reject spender approval request])
allow_spend -- Yes --> sign([Sign spender approval request])
allow_spend -- No --> reject([Reject spender approval request])
%% CSS-based class defs don't work
classDef green stroke:green;
classDef red stroke:red;
classDef yellow stroke:#e9c46a;
class sign green
class spender_approval yellow
class reject red
Revoke Pledge
WIP
This section is still work in progress.
Handling Signature Requests
We categorize all signature requests received by the in-page provider as one of the following categories:
- Sign in request
- Payment request
- Spender approval request
- Unknown
We cannot interpret all signature requests as one of the first three categories, hence the need for an unknown category. If that's the case, we reject the request and direct the user use the dapp key to continue.
Identifying sign in requests is challenging, because there is no standard format to prove ownership of an address.
Identifying payment and spender approval requests is challenging, because, while we can simulate the outcome of on-chain signatures to learn the outcome, off-chain signatures can lead to on-chain transactions as well and there is no standard format that can be used to interpret the signed data programmatically. See the Token Transfer Traces document for more details.
Handling Sign In Requests
WIP
This section is still work in progress.
Handling Payment and Spender Approval Requests
Data Needed
We need to extract the following data from the on- and off-chain signature requests for the payment and spender approval dialogs:
- Native token spent on network fees
- Native token transferred
- Fungible token transferred
- NFT transferred
- Spender approval
- Transfer recipient
- Native token received
- Fungible token received
- NFT received
In addition, we'll need to know the USD value of tokens to prevent the user misidentifying what value the token has. We can query the USD values through blockchain APIs.1
On-Chain Signatures
We can use transaction simulation to extract the data we need from on-chain signature requests.
WIP
This section is still work in progress.
Off-Chain Signatures
There is no universal solution to extract the data we need from off-chain signature requests.
Off-chain signature requests that are payment or spender approval2 requests typically follow the EIP-712 standard, but the standard only defines the format of the signed data, not its semantics. Therefore, in order to extract the data needed,, we have to support application-specific protocols such as Seaport. We should drive standardization in the ecosystem to reduce the implementation burden on us.
WIP
This section is still work in progress.