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
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
Name | Value |
---|---|
AA_BASE_GAS_COST | 15000 |
AA_BASE_GAS_COST_RIP7712 | 10000 |
AA_NONCE_MANAGER | tbd |
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.
The legacy nonce
account parameter use
The legacy 64-bit nonce
account parameter is used when the nonceKey
parameter of the AA_TX_TYPE
transaction
is set to 0.
The legacy nonce
account parameter is also use for transactions initiated by EOAs, for the CREATE
opcode and for EIP-7702 authorizations.
Account deployment transaction does not increment the legacy nonce
The first AA_TX_TYPE
transaction that contains a deployer
and deployerData
fields to create the sender
account
does not increment the sender
's legacy nonce
account parameter even in case the key
parameter is set to 0.
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.
Account deployment transaction does not increment the legacy nonce
The EIP-684 explicitly prevents deployment of contracts for accounts with
non-zero nonce value. This rule collides with the normal flow of incrementing the sender
nonce before execution
of a transaction starts.
However, EIP-161 guarantees that the nonce
of a newly created account
is set to 1
on creation.
This guarantees that the sender
deployment transaction can pass the EIP-684 rule check and still increment the nonce.
Note that revert in the creation frame makes the AA_TX_TYPE
transaction invalid and sender
's nonce
cannot be incremented without successfully deploying its code.
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
EIP-7702 authorization revocation with a nonce bump
In EIP-7702 the EOA is able to revoke an "authorization tuple" it has previously signed as long as it has not been
included on-chain.
This can be done by incrementing the EOAs nonce
, which in turn can only be done by sending a new transaction.
With RIP-7712, however, there exists a new way of sending a transaction without affecting the legacy nonce
field.
Such a transaction will not invalidate the previously signed "authorization tuple" either.
Users who are unaware of this change may not expect an "authorization tuple" to remain valid after sending a different
transaction and should be aware of the existence of RIP-7712 and multidimensional nonces.
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.