ERC-7699: ERC20 Payment reference extension

ERC pull request: Add ERC: ERC20 Payment reference extension by radeksvarz · Pull Request #399 · ethereum/ERCs · GitHub

A minimal standard interface for ERC20 tokens allowing users to include a unique identifier (payment reference) for each transaction to help distinguish and associate payments with orders and invoices.

Requires: EIP-20, EIP-165

Abstract

The ERC20 token standard has become the most widely used token standard on the Ethereum network. However, it does not provide a built-in mechanism for including a payment reference (message) in token transfers. This proposal extends the existing ERC20 token standard by adding minimal methods to include a payment reference in token transfers and transferFrom operations. The addition of a payment reference can help users, merchants, and service providers to associate and reconcile individual transactions with specific orders or invoices.

Motivation

The primary motivation for this proposal is to improve the functionality of the ERC20 token standard by providing a mechanism for including a payment reference in token transfers, similar to the traditional finance systems where payment references are commonly used to associate and reconcile transactions with specific orders, invoices or other financial records.

Currently, users and merchants who want to include a payment reference in their transactions must rely on off chain external systems or custom payment proxy implementations. In traditional finance systems, payment references are often included in wire transfers and other types of electronic payments, making it easy for users and merchants to manage and reconcile their transactions.

By extending the existing ERC20 token standard with payment reference capabilities, this proposal will help bridge the gap between traditional finance systems and the world of decentralized finance, providing a more seamless experience for users, merchants, and service providers alike.

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.

Any contract complying with EIP-20 when extended with this ERC, MUST implement the following interface:

// The EIP-165 identifier of this interface is 0xxxxxxx - to be updated once ERC number is assigned

interface IERCXXXX {

function transfer(address to, uint256 amount, bytes calldata paymentReference) external returns (bool);

function transferFrom(address from, address to, uint256 amount, bytes calldata paymentReference) external returns (bool);

event Transfer(address indexed from, address indexed to, uint256 amount, bytes indexed paymentReference);

}

These transfer and transferFrom functions MUST emit Transfer event with paymentReference parameter.

paymentReference parameter MAY be empty - example: emit Transfer(From, To, amount, "");

paymentReference parameter is not limited in length by design, users are motivated to keep it short by calldata and log data gas costs.

Transfers of 0 amount MUST be treated as normal transfers and fire the Transfer event.

Rationale

Parameter name

The choice to name the added parameter paymentReference was made to align with traditional banking terminology, where payment references are widely used to associate and reconcile transactions with specific orders, invoices or other financial records.

The paymentReference parameter name also helps to clearly communicate the purpose of the parameter and its role in facilitating the association and reconciliation of transactions. By adopting terminology that is well-established in the financial industry, the proposal aims to foster a greater understanding and adoption of the extended ERC20 token standard.

Backwards Compatibility

This extension is fully backwards compatible with the existing ERC20 token standard. The new functions can be used alongside the existing transfer and transferFrom functions. Existing upgradable ERC20 tokens can be upgraded to include the new functionality without impact on the storage layout; new ERC20 tokens can choose to implement the payment reference features based on their specific needs.

ERC20 requires its Transfer(address indexed _from, address indexed _to, uint256 _value) event to be emitted during transfers, thus there will be duplicitous data logged (from, to, amount) in two events.

Security Considerations

Payment reference privacy: Including payment references in token transfers may expose sensitive information about the transaction or the parties involved. Implementers and users SHOULD carefully consider the privacy implications and ensure that payment references do not reveal sensitive information. To mitigate this risk, implementers can consider using encryption or other privacy-enhancing techniques to protect payment reference data.

Manipulation of payment references: Malicious actors might attempt to manipulate payment references to mislead users, merchants, or service providers. This can lead to:

  1. Legal risks: The beneficiary may face legal and compliance risks if the attacker uses illicit funds, potentially impersonating or flagging the beneficiary of involvement in money laundering or other illicit activities.

  2. Disputes and refunds: The user might discover they didn’t make the payment, request a refund or raise a dispute, causing additional administrative work for the beneficiary.

To mitigate this risk, implementers can consider using methods to identify proper sender and to generate unique and verifiable related payment references.

This ERC was discussed during the BeerFi Prague chaindev meetup. There were 2 points for consideration:

A. paymentReference type - initially bytes32 was considered in order to motivate users to either use short references (as is common in TradFi) or rather use Keccak 256 hash of the reference content. Conclusion was that we should rather keep the options open as one use case examples could be to pass a signed reference, where the token contract checks the signature and potentially refuses the transfer if invalid.

B. The emitted Transfer event contains both - the reference data and also the from, to, amount data. That is duplicate to ERC-20 Transfer event. In fact 2 events are fired:

B1)

  1. ERC7699.Transfer(from, to, amount, paymentReference)
  2. ERC20.Transfer(form, to, amount)

There could be the option to rather emit:

B2)

  1. ERC7699.PaymentReference(paymentReference)
  2. ERC20.Transfer(form, to, amount)

However for that case the offchain indexing / wallets / BackEnds would need to listen to and aggregate information from both events.

We would like to have the sound discussion on this.

The 3rd option was mentioned:

B3)

ERC7699.Transfer(from, to, amount, paymentReference) MUST be emitted also in the case the ERC20.transfer(to, amount) op is done. In that case paymentReference is to be emitted empty ( “” ).
By that the indexers, wallets, etc. can rely solely on this event for contracts compliant with this ERC.