| eip | tbd |
|---|---|
| title | Multi-Chain Payment Request Standard |
| description | A standard for payment requests supporting multiple tokens across multiple blockchains with signature verification |
| author | @aromeoes |
| discussions-to | tbd |
| status | Draft |
| type | Standards Track |
| category | ERC |
| created | 2025-01-28 |
- In order for this url format to be compatible with QR codes, we would need to have a compact form factor for the JSON. Something like mapping a set of contracts to an int that gets decoded on the wallet. Further research needed to understand if this introduces vulnerabilities.
This EIP defines a standard URL format for payment requests that simplifies communication between payment requestors and wallets. It extends the functionality pioneered by EIP-681 to include willingness to accept multiple tokens in multiple chains, expiration and signatures. It also implements a compression mechanisms to keep url length below 500 characters to be friendly towards being displayed in QR codes, and NFC chips.
Current payment request standards like EIP-681 have limitations:
- Single-chain focus: Cannot express acceptance of the same asset across multiple chains
- Single-token focus: Cannot express willingness to accept multiple assets
- Security concerns: No cryptographic proof of the payment request origin makes it prone to phising
- No expiration mechanism: Payment requests remain valid indefinitely
As the cross-chain ecosystem grows, users hold assets across various networks. This standard enables seamless payment experiences where users can pay with their preferred token on their preferred chain, while merchants can cryptographically sign requests for verification.
Payment requests use the following URI scheme:
payment:?data=<base64-encoded-payload>
The payload is a JSON object that MUST be Base64-encoded:
{
"options": [
{
"chainId": 1,
"token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"amount": "1000000",
"expiration": 19500000
},
{
"chainId": 137,
"token": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
"amount": "1000000",
"expiration": 55000000
}
],
"metadata": {},
"signature": "0x..."
}An array of payment options. Each option MUST contain:
chainId(number, REQUIRED): The EIP-155 chain IDtoken(string, OPTIONAL): The token contract address. If omitted, indicates the native token of the specified chainamount(string, REQUIRED): The amount in the smallest unit of the token (e.g., wei for ETH, smallest unit for ERC-20)expiration(number, REQUIRED): The block number on the specified chain after which this option is no longer valid
An object containing arbitrary key-value pairs for additional information. The structure and interpretation of metadata is left to implementers.
An EIP-712 signature of the payment request data, signed by the payment requestor.
The signature MUST follow EIP-712 standard with the following structure:
A merchant accepting 1 USDC on either Ethereum or Polygon:
const paymentRequest = {
options: [
{
chainId: 1,
token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
amount: "1000000",
expiration: 19500000
},
{
chainId: 137,
token: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
amount: "1000000",
expiration: 55000000
}
],
metadata: {
orderId: "12345",
description: "Payment for order #12345"
},
signature: "0x..."
};
const encoded = btoa(JSON.stringify(paymentRequest));
const uri = `payment:?data=${encoded}`;By allowing multiple tokens and multiple chains, wallets can simplify users payment experience by showing any of the available options to pay with where balance is .
Block numbers are used for expiration as they provide more precise control than timestamps. Since block times vary by chain, each option has its own expiration.
EIP-712 provides a standard way to sign structured data that can be verified by wallets and shown to users in a human-readable format.
Leaving metadata unstructured allows for evolution and implementation-specific features without requiring standard updates.
Wallets SHOULD implement signature verification to ensure payment requests originate from claimed sources. This MAY include:
- ENS resolution to verify domain ownership
- DNS TXT record verification
- Maintaining lists of known/verified requestors
The combination of amount, expiration, and metadata should make each payment request unique. Implementers SHOULD track fulfilled payments to prevent double-spending.
Requestors MUST make sure that each payment request has a unique address.
- Compression: Future versions may specify compression schemes to reduce URI length
- Advanced routing: Support for payment routing through specific contracts or protocols
- Partial payments: Allow requests that can be fulfilled partially
- Recurring payments: Extension for subscription-based payment requests
Copyright and related rights waived via CC0.