RIP-7712: Enable RIP-7560 transactions using a two-dimensional nonce

An RIP-7560 transaction modification that allows Smart Contract Accounts to define their own transaction sequencing


Metadata
Status: DraftStandards Track: CoreCreated: 2023-09-01
Authors
Vitalik Buterin (@vbuterin), Yoav Weiss (@yoavw), Alex Forshtat (@forshtat), Dror Tirosh (@drortirosh), Shahaf Nacson (@shahafn)
Requires

Abstract


An RIP-7560 transaction modification that replaces the existing nonce-based sequencing mechanism of Ethereum with an on-chain pre-deployed contract in order to provide Smart Contract Accounts with the flexibility they need to support some advanced use cases.

Motivation


The traditional nonce-based system provides guarantees of transaction ordering and replay protection, but does so at the expanse of configurability. Accounts are not able to express their intentions like "allow these three transactions to be mined in whatever order" or "these two sets of transactions must have separate sequential nonces".

However, with Smart Contract Accounts this creates a bottleneck for some use-cases. For example, Smart Contract Accounts designed to be operated by multiple participants simultaneously, will require these participants to coordinate their transactions to avoid invalidating each other.

Another example when this can also be a limitation is a case where there are separate execution flows. A configuration change may require multiple participants to co-sign a transaction but a regular operation does not. With sequential nonces, all operations will have to be halted until the configuration change is executed.

Having a more agile ordering and replay protection system will significantly improve the user experience with RIP-7560.

Additionally, this change is required for the Native Account Abstraction to achieve feature parity and compatibility with ERC-4337, as all ERC-4337 Smart Contract Accounts already use the solution described below.

Specification


Constants

NameValue
AA_BASE_GAS_COST15000
AA_BASE_GAS_COST_RIP771210000
AA_NONCE_MANAGERtbd

Non-sequential nonce support

We propose an introduction of the nonceKey parameter to provide a second dimension for the RIP-7560 transaction's nonce parameter.

The two-dimensional nonce value of the transaction is represented as uint256 nonceKey || uint256 nonceSequence value. The contract account nonce is then defined as a mapping address account => uint256 nonceKey => uint256 nonceSequence. This approach guarantees unique transaction nonce and hash but removes the requirement of nonces being sequential numbers.

This two-dimensional nonce mechanism is exposed to the EVM in a NonceManager pre-deployed contract located at the AA_NONCE_MANAGER address.

The two-dimensional nonce is validated and incremented on-chain as part of a AA_TX_TYPE transaction validation before the rest of the validation code.

Nonce validation

We propose to introduce a new validation frame to the RIP-7560 transaction validation flow. This validation frame performs an on-chain nonce validation and runs before all other frames in a transaction.

If nonceKey is zero (non-existent), the nonce field is compared to the system nonce, and then the system nonce is incremented. The transaction's base cost is A_BASE_GAS_COST.

If nonceKey is non-zero, then the NonceManager is called to validate and increment the nonce for this key, and the base cost is AA_BASE_GAS_COST_RIP7712, as the NonceManager frame is paid separately. In this case, the old system nonce is not checked and not incremented.

Deployment transaction

During the account deployment transaction, the nonceKey MUST be zero. The old system nonce parameter is not incremented before the transaction: the CREATE or CREATE2 opcode used by the deployer will cause the nonce to be incremented to 1 according to EIP-161.

Nonce validation frame

Before the first RIP-7560 transaction type defined validation frame is applied during the validation phase, the NonceManager is invoked with the following data:


The gas costs of this validation frame are counted towards the total for a transaction, and is deducted from the account's validationGasLimit.

Nonce query frame

In order to query its current nonceSequence for a given nonceKey, the user performs a view call to the NonceManager contract with the following data:


The returned value of this call is the current nonceSequence that can be used in the nonce validation frame.

NonceManager Pseudocode


NonceManager Bytecode and deployment

TODO.

Rationale


Creating a pre-deployed contract instead of modifying an account data structure

While there is no technical benefit to either option, allowing EVM code to control the nonce seems to be a smaller change to the Ethereum protocol and is more aligned with the vision of Account Abstraction.

Backwards Compatibility


As actual nonce value was never observable inside the EVM, there should be no major complications caused by the migration to a different nonce mechanism.

Applications should not assume that eth_getTransactionCount method returns the total transactions for an account

Security Considerations


Smart Contract Accounts that need to enforce the sequence of transaction execution must apply appropriate restrictions on the nonceKey value.

In order to require the incremental sequential nonce behaviour on-chain, the contracts may choose to require(nonceKey == 0).

Copyright


Copyright and related rights waived via CC0.