Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ERC: EIP-712 Extensions for Account Abstraction #693

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions ERCS/erc-7803.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
---
eip: 7803
title: EIP-712 Extensions for Account Abstraction

Check failure on line 3 in ERCS/erc-7803.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

unable to read file `erc-712.md`: Io

error[preamble-refs-title]: unable to read file `erc-712.md`: Io --> ERCS/erc-7803.md:3:8 | 3 | title: EIP-712 Extensions for Account Abstraction | ^^^^^^^ referenced here | = help: see https://ethereum.github.io/eipw/preamble-refs-title/
description: Improvements for EIP-712 to support smart contract accounts.

Check failure on line 4 in ERCS/erc-7803.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

unable to read file `erc-712.md`: Io

error[preamble-refs-description]: unable to read file `erc-712.md`: Io --> ERCS/erc-7803.md:4:31 | 4 | description: Improvements for EIP-712 to support smart contract accounts. | ^^^^^^^ referenced here | = help: see https://ethereum.github.io/eipw/preamble-refs-description/
author: Francisco Giordano (@frangio)
discussions-to: https://ethereum-magicians.org/t/erc-7803-eip-712-extensions-for-account-abstraction/21436
status: Draft
type: Standards Track
category: ERC
created: 2024-10-08
requires: 712
---

## Abstract

This ERC improves on [EIP-712] signatures to better support smart contract accounts by 1) introducing signing domains as a way to prevent replay attacks when private keys are shared across accounts, and 2) allowing dapps and wallets to coordinate on the method that will be used to authenticate the signature.

Check failure on line 16 in ERCS/erc-7803.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

unable to read file `erc-712.md`: Io

error[markdown-link-status]: unable to read file `erc-712.md`: Io --> ERCS/erc-7803.md | 16 | This ERC improves on [EIP-712] signatures to better support smart contract accounts by 1) introducing signing domains as a way to pr... | = help: see https://ethereum.github.io/eipw/markdown-link-status/

[EIP-712]: ./erc-712.md

## Motivation

### Signing Domains

Standards like [ERC-1271] and [ERC-6492] give smart contract accounts (SCAs) the ability to produce signatures that an application can authenticate without knowledge of the abstract rules of the account. This is an important primitive for applications, as the account owner is able to authorize a third-party to act on its behalf without interacting with the chain.

[ERC-1271]: ./erc-1271.md
[ERC-6492]: ./erc-6492.md

Smart contract accounts may be "owned" by cryptographic keys whose signatures are used to authorize the use of the account. There is not necessarily a one-to-one mapping between keys and accounts, because a single key may control multiple accounts, so care must be taken to prevent replay attacks across them. This is done by binding a signature to a particular account.

EIP-712 introduced a scheme where signatures can be bound to a verifying domain, which corresponds to the protocol contract that will authenticate a signature. Reusing this mechanism to additionally bind a signature to the domain of the smart contract account runs into a large amount of complexity and attack surface (see [ERC-7739]), as well as yet unresolved issues with account composability (SCAs that control other SCAs). This ERC introduces *signing domains* in addition to verifying domains to natively enable wallets to generate smart contract account signatures with replay protection.

[ERC-7739]: ./erc-7739.md

### Authentication Methods

ERC-1271 is a minimal and very general interface that has been very effective. It requires the contract code to be already deployed by the time the signature needs to be authenticated, so ERC-6492 extends ERC-1271 to support that use case. In the future additional methods may need to be developed.

Support for these methods across protocols is currently lacking and is a major pain point for the Account Abstraction roadmap. Where ERC-1271 is supported, it is not necessarily used uniformly, in particular some contracts attempt `ECRECOVER` prior to invoking `isValidSignature` while others do the opposite, which will result in very different semantics post [EIP-7702].

Check failure on line 39 in ERCS/erc-7803.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

unable to read file `erc-7702.md`: Io

error[markdown-link-status]: unable to read file `erc-7702.md`: Io --> ERCS/erc-7803.md | 39 | Support for these methods across protocols is currently lacking and is a major pain point for the Account Abstraction roadmap. Where... |

[EIP-7702]: ./erc-7702.md

This ERC addresses this by allowing dapps to communicate the types of signatures a protocol's contracts support, i.e., which authentication methods will be used, and in what order.

## 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.

Requests for typed data signatures via JSON-RPC (`eth_signTypedData`) or client libraries are extended with the following optional properties:

- `signingDomains`
- `authMethods`

These new properties are used alongside the existing ones, i.e., `types`, `primaryType`, `domain`, and `message`.

The signature returned in response to the request MAY be of any size, and in the absence of `authMethods` it MUST be treated opaquely as the type of the signature is not known.

### `signingDomains`

This property is an array of smart contract account domains. Each member of the array is an object with the following keys:

- `types`: An object with the same format as EIP-712 `types` with at least an `EIP712Domain` key.
- `domain`: An object that is valid with respect to the type `EIP712Domain` described in `types`.

From right to left the array lists the chain of accounts through which the signer ultimately has control over the "outermost" signing domain (i.e., that listed first).

For example:

1. A dapp requests an EIP-712 signature to a connected account via JSON-RPC. `signingDomains` is empty or undefined.
2. The connected account is a multisig, so it requests EIP-712 signatures from its signers, prepending the domain of the multisig to `signingDomains`, which is now an array of length 1.
3. One of the signers uses a smart contract account controlled by an ECDSA key held in a hardware wallet, so their wallet requests an EIP-712 signature from the hardware wallet, prepending the domain of the smart contract account to `signingDomains`, which is now an array of length 2.
4. The signer verifies the contents of the signature in their hardware wallet. They are able to see that they are signing a message intended for a particular dapp domain, on behalf of their smart contract account (closest signing domain), as a member of the multisig (furthest signing domain).

#### Encoding of data to be signed

In the presence of `signingDomains` the account should encode the message to be signed according to the following recursive procedure:

- `encodeForSigningDomains(signingDomainSeparators : [𝔹²⁵⁶], verifyingDomainSeparator : 𝔹²⁵⁶, message : 𝕊) =`
- If `signingDomainSeparators = [first, ...others]`: `"\x19\x02" ‖ first ‖ encodeForSigningDomains(others, verifyingDomainSeparator, message)`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is first the initial dapp domain? If so, I think dapp would be more explicit:

Suggested change
- If `signingDomainSeparators = [first, ...others]`: `"\x19\x02" ‖ first ‖ encodeForSigningDomains(others, verifyingDomainSeparator, message)`
- If `signingDomainSeparators = [dapp, ...others]`: `"\x19\x02" ‖ dapp ‖ encodeForSigningDomains(others, verifyingDomainSeparator, message)`

Copy link

@howydev howydev Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC - signingDomainSeparators is a new addition and will only contain account domains. The dapp domain is the domain in L54

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes these are distinct from the dapp domain.

- If `signingDomainSeparators = []`: `encode(domainSeparator, message)`, where `encode` is defined by EIP-712.

`signingDomainSeparators` is the array of hashes of the domains included in `signingDomains`, in the same order, computed according to EIP-712's `hashStruct`.

### `authMethods`

This property is an array of supported signature authentication methods, listed in the order that the verifying domain tries them.

Each member of the array is an object with the following keys:

- `id`: An string that identifies the method. It may be one of:
- `ECDSA`: ECDSA signatures by Externally Owned Accounts.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel we the spec should suggest priority for ERC-1271 if there's code in the address. Just as we do in SignatureChecker since after EIP-7702, the validation mechanism should decide whether to prioritize ECDSA or ERC-1271.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that if there's code ERC-1271 should take priority but not all contracts implement it that way (e.g., prior versions of OpenZeppelin Contracts didn't), so if a dapp needs a signature for one of those contracts it should be possible to express that order of preferences.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is explained in the Motivation section too, let me know if it's not clear.

- `ERC-{n}`: A standard type of signature specified by an ERC. `n` must not be padded with zeros.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an authentication method other than ERC-1271? If 1271 is generalized enough I think this can be simplified to just ECDSA or ERC-1271.

In the case we want to make this ERC more broadly compatible, then it may make sense to define the signature algorithms supported by other networks (e.g. ed25519 in cosmos). I feel this is not the case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an authentication method other than ERC-1271?

Yes, ERC-6492 is another standard that is mentioned earlier in the Motivation section. It covers a scenario that ERC-1271 doesn't (predeploy contracts). I'd rather keep this generic than listing the standards that exist now.

- `parameters` (optional): An array of method-specific parameters.

### JSON Schema

```javascript
{
type: 'object',
properties: {
types: {$ref: '#/$defs/EIP712Types'},
primaryType: {type: 'string'},
domain: {type: 'object'},
message: {type: 'object'},
signingDomains: {
type: 'array',
items: {$ref: '#/$defs/EIP712Types'}
}
authMethods: {
type: 'array',
items: {
type: 'object',
id: {type: 'string'},
parameters: {type: 'array'},
required: ['id'],
},
}
},
required: ['types', 'primaryType', 'domain', 'message'],
$defs: {
EIP712Types: {
type: 'object',
properties: {
EIP712Domain: {type: 'array'},
},
additionalProperties: {
type: 'array',
items: {
type: 'object',
properties: {
name: {type: 'string'},
type: {type: 'string'}
},
required: ['name', 'type']
}
},
required: ['EIP712Domain']
}
}
}
```

## Rationale

TODO

## Backwards Compatibility

TODO

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
Loading