Skip to content



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. 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.

Passwordless login on iOS with WebAuthn

Passwordless login on iOS with WebAuthn.

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.

Apple Pay prompt on iOS

Apple Pay prompt on iOS.

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:

  1. 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.
  2. 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


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:

  1. Sign in request
  2. Payment request
  3. Spender approval request
  4. 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


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.


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.


This section is still work in progress.

  1. A faulty or malicious blockchain API can send wrong values. This an attack vector that we don't against currently. 

  2. Spender approval with off-chain signatures is rare, but it's standardized in EIP-2612.