Skip to content

Latest commit

 

History

History
49 lines (33 loc) · 3.31 KB

ERC2771.md

File metadata and controls

49 lines (33 loc) · 3.31 KB

ERC-2771: Secure Protocol for Native Meta Transactions

My notes are either copied or rewritten from : https://eips.ethereum.org/EIPS/eip-2771

This allows a contract that receives a request(meta-transaction) to check if the msg.sender is in a trusted Forwarders list, and if all checks pass it can swap out the msg.sender for the address approved by the transaction signer recieved as the last 20 bytes of the calldata.

A third party can authorise a meta-transaction and forward this to a Gas Relay (Forwarder).

How it works:

  1. Transaction Signer: Signs & sends transactions to a Gas Relay
  2. Gas Relay: Receives signed requests off-chain from Transaction Signers and pays gas to turn it into a valid transaction that goes through a Trusted Forwarder
  3. Trusted Forwarder: A contract trusted by the Recipient to correctly verify signatures and nonces before forwarding the request from Transaction Signers
  4. Recipient: A contract that accepts meta-transactions through a Trusted Forwarder

Definitions

Transaction Signer: Signs & sends transactions to a Gas Relay

Gas Relay: Receives signed requests off-chain from Transaction Signers and pays gas to turn it into a valid transaction that goes through a Trusted Forwarder

Trusted Forwarder: A contract trusted by the Recipient to correctly verify signatures and nonces before forwarding the request from Transaction Signers

Recipient: A contract that accepts meta-transactions through a Trusted Forwarder

The Recipient contract can then extract the Transaction Signer address by performing 3 operations:

  1. Check that the Forwarder is trusted.
  2. Extract the Transaction Signer address from the last 20 bytes of the call data and use that as the original sender of the transaction (instead of msg.sender)
  3. If the msg.sender is not a trusted forwarder (or if the msg.data is shorter than 20 bytes), then return the original msg.sender as it is.

RULES

The Recipient MUST check that it trusts the Forwarder to prevent it from extracting address data appended from an untrusted contract. This could result in a forged address.

To provide this discovery mechanism a Recipient contract MUST implement this function:

function isTrustedForwarder(address forwarder) external view returns(bool);

isTrustedForwarder MUST return true if the forwarder is trusted by the Recipient, otherwise it MUST return false. isTrustedForwarder MUST NOT revert.
Internally, the Recipient MUST then accept a request from forwarder.
isTrustedForwarder function MAY be called on-chain, and as such gas restrictions MUST be put in place.
It SHOULD NOT consume more than 50,000 gas

Security Considerations

A malicious forwarder may forge the value of _msgSender() and effectively send transactions from any address.
Therefore, Recipient contracts must be very careful in trusting forwarders.
If a forwarder is upgradeable, then one must also trust that the contract won’t perform a malicious upgrade.

In addition, modifying which forwarders are trusted must be restricted, since an attacker could “trust” their own address to forward transactions, and therefore be able to forge transactions. It is recommended to have the list of trusted forwarders be immutable, and if this is not feasible, then only trusted contract owners should be able to modify it.