# 7702 Best Practices ## Open Questions/ TODOs - How to call a 7702 authorization? - How should 7702 authorizations displayed in general - Should be considered as similar to expose your private key! - Disallowing signing of `null` nonce, would conflict with one of the feature of long standing authorizations - Should be changed to clearly indicate this, not to prevent this - Add a section on what a reasonable nonce is - Signing a too high nonce might also have security implications ## Introduction [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) introduces a new transaction type that allows code execution in the context of an EOA. Under the current proposal, in order for an EOA to authorize the code that should be executed, it has to sign the `address` of the account containing the code to execute, and optionally the current `nonce` and a `chainId`. It is important to understand the semantics of each of these parameters and the security implications of not signing `nonce` or `chainId`. This document contains recommendations and guidelines in regards to this. The main use-case that this document focuses on is using the new features introduced by EIP-7702 as a means to implement account abstraction features on existing EOAs. ## Security Considerations ### Multiple 7702 Authorizations An EOA is able to sign multiple EIP-7702 authorizations that authorize different codes to be executed in its context. If multiple valid signatures exist, there is no guarantee as to which one, if any, will actually be used in a transaction. The transaction signer (not the EOA) makes the ultimate decision in which ones to include in a transaction. This can lead to unexpected behaviour for the user in cases where they have multiple valid EIP-7702 signatures. While this has similar security consideration to proxies, it has the added implication that, with multiple EIP-7702 authorizations, it is not possible to enforce logic when "changing the implementation" address; a new transaction can be executed with the EOA using different code by just using a different EIP-7702 authorization without the old implementation being able to implement any logic that controls the update process, or have any guarantees that no other code was executed in the context of the account. A concrete example where this can be an issue in the context of accounts is if the user signs EIP-7702 authorizations upgrading their account to an SCA with colliding storage usage. This means that certain invariants that the SCA implementations maintain on their storage or `CALL`s to other contracts can no longer be relied on, as the other implementation may break them. The current Safe implementation relies on a `mapping(address => address)` to be a well formed linked list of owners, if an EOA would upgrade itself to a Safe, then a parallel EIP-7702 authorization could very easily break the linked list invariant and add inadvertently add shadow owners to the account. Some of this can be solved by having storage namespacing which is described below in the contract guidelines section. ### Public EIP-7702 Signatures Once an EIP-7702 signature is used in a transaction included on the blockchain, it becomes public. Once the EIP-7702 signature is used once, it must be assumed that any one else, including malicious actors, can replay the signature in order to execute their own transaction where the EOA has code. This means that additional authorization mechanisms should be implemented by contracts intended used with EIP-7702, unless they are designed to be permissionless in nature. Another example of a potential issue caused by this would be a transaction that transfers an ERC-721 to an EOA, a malicious actor could potentially DoS that transaction by submitting an identical transaction but with a signed EIP-7702 authorization that sets code on the EOA that does not correctly implement token callback functions, causing the transfer to revert. Note that this has some assumptions on the behaviour of such a transaction (it must be to a contract with some sort of replay protection that does not revert when the transfer reverts - a concrete example would be a Safe transferring a ERC-721 to the EOA with a Safe transaction that is configured to not revert if the transaction itself reverts). In order to avoid potential issues with signatures becoming public, it is recommended that EOAs should only sign EIP-7702 authorizations with a nonce, to allow for a protocol-level way to revoke the signature if it starts having problems. ### Polymorphic Accounts With EIP-7702, accounts are polymorphic in that they can, across transactions, behave as a contract of an EOA (with a zero `EXTCODESIZE`) as well as being the `ORIGIN` (`tx.origin` in Solidity) or generally speaking being able to compute an ECDSA signature that recovers to an account while containing code. Protocols cannot make assumptions central to their security about `EXTCODESIZE` being zero for EOAs. ## Contract Guidelines While theoretically any contract can be used with EIP-7702 we propose some contract guidelines in order to maximize interoperability across contracts. - Build-in revocation to invalidate a 7702 authorization - For example, see the reference proxy implementation for an invalidation mechanism that relies on an external contract which can be invoked by the EOA. - Another possible strategy would be to always revert after a specific block or timestamp as a way to implement time-bound EIP-7702 authorization methods. - In order to more easily support EOAs migrating from one contract to another, contracts that are intended to be used with EIP-7702 should implement storage namespacing (https://github.com/ethereum/solidity/issues/597#issuecomment-1537533170) - Alternatively, they could use a storage holder pattern - Contracts should be deployed with `CREATE2` to have some guarantees of what code is at a specific address, this is more important for EIP-7702 authorizations that don't sign for a specific chain. - Note that even with `CREATE2` there is no 100% guarantee that the code at a specific address is always the same (see [create3](https://blog.solichain.com/the-ultimate-guide-to-create-create2-and-create3-cc6fe71c6d40) for example). For a reference implementation of a proxy that is intended to be used with EIP-7702, see: <https://gist.github.com/lightclient/7742e84fde4962f32928c6177eda7523> ## Signing Parameters ### Code Address By default wallet should **only allow signing of addresses where the contracts that are known** to follow the guidelines, and only allow all contracts as an opt in feature. See above for a reference proxy implementation intended for EIP-7702. ### Nonce The current transaction count of the account or `null`. Signing a value of `null` would make the EIP-7702 authorization valid for ever and provide to in-protocol mechanism for revoking the signature. Therefore, it is recommended that wallets **do not allow signing of nonce `null`**. ### Chain Id Signing the chain id ensures that the code authorization cannot be reused cross chains. This is important as it cannot always be guaranteed that the same code exists at the same address across multiple chains. That being said there are use cases that can benefit from the possibility to replay authorizations cross chain. Examples: - Cross chain "upgrade-like" experience. The flow would allow a users to sign one message for all chains and throws away the key (or that the key was generated in the first place in the trustless manner, i.e. Nicks method). When asking the user for a signature it is important that they understand the risk of cross-chain replayability. Therefore the recommended **default is to not allow transactions with chain id `0`**, and only make this an opt in feature. Wallets should always make sure that they display for which chain a code authorization is signed and if possible check if it corresponds to the connected network.