Abstract
ERC-2771 is a commonly-used standard for meta-transactions that uses one or more trusted forwarders. This EIP extends ERC-2771 to provide support for trustless account abstraction.
Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
The key words "Trusted Forwarder", and "Recipient" in this document are to be interpreted as described in ERC-2771.
Forwarder Interface
pragma solidity ^0.8.0;
interface IForwarder {
function isForwardedTransaction() external view returns (bool)
}
Extracting the Sender and Forwarder
When a function of a Recipient is called, the Recipient MUST staticcall the isForwardedTransaction()
function of the caller. If this either reverts or returns the boolean value false, the transaction MUST be treated normally, with the sender being the caller, and the Forwarder set to the zero address. If this returns the boolean value true, the transaction MUST be considered a forwarded transaction with the sender being extracted as defined in ERC-2771, and the Forwarder set to the caller.
Recipient Extensions
When a Recipient contract takes, as a parameter of a function, an address, the Recipient should include an overload of that function that takes two addresses there instead. The first address represents the Forwarder, and the second address represents the address under the control of that Forwarder. If more than one address parameter is taken (for example, ERC-20's transferFrom
), only the overload that takes two addresses for each address parameter is needed. The original function should have the same effect as the overloaded function with the forwarder addresses set to the zero address.
For example, ERC-20 would be extended with the following functions:
function transfer(address toForwarder, address toAddress, uint256 amount);
function approve(address spenderForwarder, address spenderAddress, uint256 amount);
function transferFrom(address fromForwarder, address fromAddress, address toForwarder, address toAddress, uint256 amount);
Rationale
The choice to simply add new address
parameters to every existing EIP instead of making new interfaces for the most commonly used EIPs is to maximize the general applicability of this EIP.
Backwards Compatibility
Existing contracts will not be able to take advantage of this EIP. This is also true of ERC-2771.
Security Considerations
A tradeoff is made: Forwarders do not need to be trusted by Recipients, but do need to be trusted by the users that use them with one or more accounts.
Copyright
Copyright and related rights waived via CC0.