EIP-3074: Sponsored Transaction Precompile


Creates a new precompile, analogous to CALL, that sets CALLER based on an ECDSA signature.

This EIP creates two precompiles:

  • CALL_PRECOMPILE - forwards a CALL, setting msg.sender according to an ECDSA signature, using a relayer-sponsee nonce for replay protection.
  • NONCE_PRECOMPILE - provides access to relayer-sponsee nonces expected by CALL_PRECOMPILE.

The proposal has several problems, the two most important are:

  • It’s incompatible with EIP-712 and the mapping selected could be used to confuse existing wallets into signing an unintended message.

  • It doesn’t include the chainID in the signed fields , as advertised. Therefore it’s open to network reply attacks.

This is the list of fields signed, and how they map to a normal Ethereum transaction:
Normal -> EIP-3074
Nonce -> Nonce
GasPrice -> GasLimit
GasLimit -> ReceiveAddress
ReceiveAddress -> Value
Value -> Data
Data -> relayer
chainId (not present)
empty (not present)
empty (not present)

Thanks for the feedback! I updated the signed fields to include chainid.

Is EIP-712 final yet? I wanted to avoid it until it’s finalized.

If a malicious website wanted to confuse a user, they’d have to present something like this:

Nonce: 3
GasLimit: 66000000000 (66 Gwei, current gas price)
ReceiveAddress: 0x0000000000000000000000000000000000Be8c72 (current block gas limit)
Value: 611382286831621467233887798921.843936019654057231 ETH (some address)

I’ve probably missed some of the specifics of the RLP offsets, but it seems like it would be a very suspicious transaction. I’m not opposed to modifying the format to make it impossible though, if you have any suggestions.

Recommend having the transaction be a 2718 typed transaction, which means grabbing a number and signing over secp256k1(keccak256(TransactionType || rlp([nonce, gaslimit, to, value, data, invoker, chainid]))). This would make it so we don’t have to worry about having the signature collide with some other future transaction type.

This wouldn’t technically be a 2718 transaction because it has no receipt and doesn’t end up in a block header, but we should reserve the transaction type number and follow the signing rules.

1 Like

Other changes I would like to see:

  1. Signature should be yParity, r, s. v shouldn’t really be used anymore.
  2. Signature first. This enables some minor optimizations and comes at no cost.
  3. data last. This is pretty minor, but having the variable length thing at the end makes some stuff a tad easier and this change comes with no cost.
  4. Remove chainId. This can be addressed by the invoker with CREATE2 using CHAIN_ID as a salt. In the case of a fork (chain ID change), the invoker can be redeployed. This can be automated with a factory. By not having a chain ID, transactions and invokers can be constructed that intentionally support replays across chains.
  5. Remove nonce and nonce checking and only include 32 bytes of extra data in the signature. The invoker can then do nonce management (or not!).
  6. Use ABI Encoding or SSZ instead of RLP encoding. We don’t need the space savings provided by RLP, and ABI encoding and SSZ are a bit easier to work with when you have fixed width data elements followed by a single dynamic length data element.
  7. Rename gaslimit to mingas. This value doesn’t represent a gas limit, but instead represents the minimum amount of gas that needs to be supplied.