Skip to content

Feature request: support ERC-681 (EIP-681) QR scanning for native + ERC-20 transfers #8022

@zhangzhongnan928

Description

@zhangzhongnan928

Summary

Uniswap Wallet (mobile and extension) does not currently parse ERC-681 payment URIs when scanned via the QR scanner. Adding support for the two simplest cases (native transfer and ERC-20 transfer) would let Uniswap users pay any merchant or peer who emits a standard payment QR.

Background

ERC-681 (https://eips.ethereum.org/EIPS/eip-681) is the standard URI format for Ethereum payment requests. It is the QR equivalent of bitcoin: URIs. Most major wallets parse it: MetaMask, Coinbase Wallet, Rainbow, Trust Wallet, Base App, imToken (partial), Bitcoin.com Wallet.

A typical payment QR looks like:

Native transfer:

ethereum:0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359@8453?value=1e16

(Send 0.01 ETH on Base)

ERC-20 transfer:

ethereum:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913@8453/transfer?address=0x54235780057CC828C92aA40e3b02053881990153&uint256=1e6

(Send 1 USDC on Base)

The format encodes target chain, recipient, token, and amount, eliminating the cross-chain footgun where a user pastes an address and selects the wrong network.

Current behaviour

Scanning either of the QRs above with the Uniswap Wallet QR scanner does not trigger a send flow. (shows "Invalid QR Code")

Proposed scope

narrow and low-risk:

  • Parse ethereum: scheme URIs from the in-app QR scanner
  • Native transfer: when no function_name is present, treat as native send. Use value parameter, switch network to chain_id if specified, prefill recipient + amount on the send screen
  • ERC-20 transfer: when function_name == transfer, target_address is the token contract. Use address parameter as recipient, uint256 as raw amount. Read decimals() from the token contract on the specified chain to render human-readable amount
  • User confirms on the standard send screen. No auto-execution

Why this matters now

Stablecoin payment flows are real and growing. Live examples emitting ERC-681 QRs:

  • Bitcoin.com Wallet (default receive QR)
  • Coinbase Wallet (receive QR)
  • MetaMask (request payment)
  • OpenPasskey terminal (20+ live merchants in Sydney accepting AUDD on Base)
  • Various account-abstraction "pay-by-QR" UX

Today, Uniswap Wallet users cannot pay these QRs without copy-pasting the address manually and re-entering the amount.

Risk assessment

Low. The spec is narrow, well-defined, and the user always confirms on the standard send screen before signing. Reading decimals() from chain is the spec's recommended path:

In case of ERC-20 token payments, if the payer client has access to the blockchain or some other trusted source of information about the token contract, the interface should display the amount in the units specified in the token contract.

Test vectors

# Native ETH transfer on Ethereum mainnet
ethereum:0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359?value=2.014e18

# Native ETH transfer on Base
ethereum:0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359@8453?value=1e16

# USDC transfer on Base (6 decimals)
ethereum:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913@8453/transfer?address=0x54235780057CC828C92aA40e3b02053881990153&uint256=1e6

# DAI transfer on Ethereum (18 decimals)
ethereum:0x6B175474E89094C44Da98b954EedeAC495271d0F/transfer?address=0x54235780057CC828C92aA40e3b02053881990153&uint256=1e18

Each should produce the same prefilled send screen as if the user typed all fields manually.

Happy to provide additional repro QRs or test on production builds if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions