With EIP-7702 looming on the horizon, developers building on Ethereum are excited to get a slew of new features when working with EOA accounts. There is still a lot of confusion around how EIP-7702 will be implemented in practice. One feature provided by EIP-7702, which hasn’t gotten nearly enough attention is the ability to create new Ethereum accounts using Nicks method. First mentioned Ethereums’ Dror Tirosh, it inspired a small R&D team at Biconomy to build a completely new account standard around it.
We call them “PREP” accounts as they’re accounts deployed through setting an EIP-7702 delegation (proxy) which can prove that the private key associated with their address is not known to anyone. This has major implications for
- Deploying new smart accounts;
- Blending the tooling and interactions for EOAs and smart accounts (the biggest stated goal of EIP-7702)
What we’ve been able to achieve:
- Up to 80% reduction in deployment costs for smart accounts.
- Proving that the account owner doesn’t know the Private Key associated with the EIP-7702 authorization - enabling Resource Locks, Time-Locks and Multi-Sigs to work with EIP-7702.
- Potential to build a portable smart account, where the user can migrate the account between multiple wallets with a seed phrase or a similar method.
Goals
We see this method as being a potential candidate to become the default way of creating new EVM accounts in the future as it combines all the best characteristics of EOA and Smart Accounts.
Beyond this, using this method makes it relatively easy for teams to develop universal tooling which works with accounts which were upgraded from EOAs and with new PREP Accounts! The goal would be to standardize a lot of whats written here into an EIP- and work with smart account and wallet providers to enable a better accounts standard for Ethereum and EVM chains.
As such, we don’t see the PREP standard as outlined here to be the final form of this proposal - we see it as being the first step towards a new account system implemented by wallets, users and developer tooling.
Until such a goal is achieved, however, Biconomy will be launching PREP support natively in the new version of the Nexus smart account and our execution environments (ERC-4337 and MEE).
Nicks’ Method
As nicely explained in this article, Nicks’ method - envisioned by Vitalik Buterin and first implemented by Nick Johnson enables “Keyless Execution”. In short, Nicks’ method works by exploiting the fact that the from
(sender) parameter of an EVM transaction can be cryptographically recovered from the rest of the parameters of the transaction.
This means that a developer can encode any EVM transaction, for example “send 5 ETH to 0xabcd…000” and - instead of signing that transaction with a private key - randomly generate the r
, s
and v
values of the transaction signature.
The developer can then use ecrecover
to learn the address for which this signature is valid. If they then send 5ETH + gas needed for execution to that address and broadcast that encoded transaction - the transaction will be successfully executed! As from the perspective of the EVM chain - it’s a validly signed transaction.
The great thing about this is that it enables developers to execute transactions from accounts for which they don’t know the private key. The article linked earlier goes through some of the more interesting use-cases for Nicks’ method, so we won’t go into it here. Instead, we’ll explore the interplay of EIP-7702 authorizations and Nicks’ method.
EIP-7702
EIP-7702 introduces the ability to delegate the control over some EOA to a contract deployed on chain. This is usually done by deploying a singleton contract and using the EIP-7702 to make the EOA address a proxy for that contract. The blockchain essentially acts as if the code of the contract has been deployed on the EOA address.
In order to set the EIP-7702 delegation, a user needs to sign an authorization message in the following format with their private key:
const message = keccak(
concat(MAGIC, rlp([chain_id, address, nonce]))
)
Where:
MAGIC
is the constant0x05
which is concatenated to all EIP-7702 messages.chain_id
is the id of the chain on which the authorization is done or0
if the message should be valid for all chains.address
is a 20-byte address of the singleton contract to which we’re delegating to.nonce
is the current nonce of the signing account.
This message and it’s associated signature (the r
, s
and y_parity
values) is then sent to the chain in the authorizations
field of a new type of transaction introduced with EIP-7702. EVM verifies the authorization and delegates the EOA to the target smart contract address - giving it all the functionalities of that contract!
If the target contract is a Smart Account which has an execute
function - this means that Bundlers/Relayers/Solvers, etc… can post instructions signed by the user on behalf of that user.
This means they can:
- Pay for the users gas (gas sponsorships),
- Allow users to pay for gas with ERC-20 tokens
- Execute multiple transactions with a single signature (e.g. ERC-20 approve + execute)
- Enable many of the much more advanced features offered by teams working in the account abstraction / chain abstraction / interop space, for example:
- Multichain execution,
- Intents,
- Scheduled transactions,
- Session key automation,
- Transactions authorized by Passkey signatures
- …
EIP-7702 Limitations
While EIP-7702 is poised to drastically improve the user experience of Ethereum and EVM there are certain (notable and widely adopted) functionalities provided by Smart Accounts today, which are not available with EIP-7702 delegated accounts.
These limitations stem from the fact that the user still has an EOA which acts as a root signer for all actions - which can override all limitations set by the smart account. This has the implication that the user can’t have multi-sig accounts (since the EOA can override all signers), can’t have time-locked account functionalities (since the EOA can execute faster than time-lock), can’t have some very popular cross-chain/interop functionalities, such as resource locks (since the EOA can sign a transaction which frontruns the source chain claim process used by resouce locks), etc…
Overriding smart accounts with EOA can be done in two ways:
- The primary method of overriding the deployed smart account is by leveraging the fact that the EOA can sign a transaction which re-delegates the EOA to another account or completely removes the delegation from the EOA. There are some attempts to mitigate this - notably ERC-7851 (enabling the deactivation of the EOA).
- A secondary method stems from the fact that some very commonly used tokens use off-chain signing to move funds around - most notably with the usage of
ERC20Permit
(ERC-2612). This means the user doesn’t even have to un-delegate the account.
Nicks’ Method + EIP-7702
Now we come to the core of this article - what if we could deploy an account for which we don’t know the private key, by combining Nicks’ method and EIP-7702 authorizations? Then, since we don’t know the private key - we could never override the smart account delegation and we could never sign an ERC20Permit
or an Permit2
message to move some tokens to another address.
This is similar to a normal CREATE2
account deployment with some unique benefits which only Nicks’ can offer - which we’ll explore further in this article.
Turns out, we can! Since the EIP-7702 authorization
looks like this:
[chain_id, address, nonce, y_parity, r, s]
Where the r
, s
and y_parity
parameters are fetched from signing the EIP-7702 authorization message demonstrated earlier. What we can do then is run the authorization process in reverse!
i. Generate a valid EIP-7702 message
First generate a valid EIP-7702 authorization message hash with the following values:
chain_id = 0
to have the message be valid on all chainssmart_account_address
to be the address of the smart account singleton contractnonce = 0
since this will be a newly deployed account, the nonce of the transaction can be zero
const messageHash = keccak256(
concat([
MAGIC_PREFIX,
rlp([
0, //chainId
smart_account_address,
0 //nonce
])
])
)
ii. Generate a random signature
After you have encoded the EIP-7702 authorization message, generate a random ECDSA signature by generating random r
and s
values. Later in this article we will demonstrate powerful new capabilities when the r
and s
values are not completely random, but this example will assume random values for the purpose of simplicity.
Notes:
- Make sure that the the
s
value is smaller thansecp256k1n/2
(as per EIP--2), this pseudocode will skip over that. - Every recoverable pair of
r
ands
(some pairs do not recover an address, but it rarely takes more than two attempts to find a valid pair) recovers two valid addresses (as the elliptic curve is symmetric and two y-coordinates match any given x-coordinate. This is represented by thev
value. Since we don’t care about the private key, we can use whicheverv
value we want (27 or 28 are available)
const r = randomBytes(32)
const s = randomBytes(32) // make sure the value is smaller than secp256k1n/2
const v = randomSelect(27,28) // we don't care about the v value, so we can use both 27 or 28
iii. Recover the signer address
Now we can recover the address for which this is a valid signature. We will not know the private key of that address!
const signature = concat([r,s,v])
const recoveredAddress = recoverAddress(messageHash, signature)
iv. Generate an EIP-7702 authorization tuple
Now that we have successfully recovered an address from a signature, we can generate the EIP-7702 authorization tuple:
// Fields must match the fields used in the `messageHash` in step i.
const authorization = {
chain_id: 0, // chainId zero means the message is valid on all chains
address: smart_account_address, // address of the smart account singleton
nonce: 0, // it's a never used account so the nonce can be 0
y_parity: v, // y_parity is a different name for the v param
r: r, // randomly generated r from step ii.
s: s, // randomly generated s from step ii.
}
v. Post the transaction onchain
By posting an EIP-7702 transaction type with this authorization as one of the authorizations in its authorizations
array - you will have successfully delegated the recoveredAddress
to the smart_contract_address
! This means that the recoveredAddress
is now a fully fledged smart account! 🥳
vi. Initialize the smart account
After we have delegated the recoveredAddress
to our desired smart account implementation, we must initialize the smart account. This usually means setting the owner(s) of the account and the signing scheme for the account. This can be one or more EOA signers, or a Passkey signer or an MPC signer, etc… The initialization part wholly depends on the implementation of the smart account itself.
Nicks’ + EIP-7702 Core Benefits
Combining Nicks’ and EIP-7702 comes with a lot of benefits even before we add the PREP specific functionalities.
- Up to 90% Gas Savings of Nicks’ + EIP-7702 One big benefit of using Nicks’ method together with an EIP-7702 authorizations is that the cost of deploying a smart account drops from ~150k gas down to ~70k gas for a general-purpose case!
With certain optimizations which assume that the account has a single EOA signer - we can achieve even greater optimizations and bring the cost of deployments down to 30k of gas - an 80*%+ reduction in cost*!
- Same address on all chains Since using the Nicks’ method with EIP-7702 is a purely cryptographic combo, the user will have the same address on all standard chains!
As Nicks’ method with EIP-7702 authorizations uses a purely cryptographic derivation of the user address and as Nicks’ method can also be used to deploy the singleton Smart Account implementation contracts - this means that the user will always have the same address on any EVM compatible chain (which has EIP-7702 support) and any future EVM compatible chain!
Limitations of Nicks’ + EIP-7702
While combining Nicks’ and EIP-7702 is a powerful combo, there are several limitations which we still need to solve:
- Frontrunning protection: The smart account which is being initialized needs to be protected from being frontrun. Since the
authorizations
tuples are publicly available in the mempool, a malicious actor could execute the transaction itself and - if the initialization function isn’t properly protected - set itself as the sole signer of the account. Since in this method, the user has to sign with achain_id = 0
in order to enable the deployment to the same address on all EVM chains - if the init method is unprotected, a malicious attacker could use that auth for other chains and set itself as the owner. - Proving that you don’t know the private key: One of the main reasons we’ve used the Nicks’ method with EIP-7702 is to have accounts for which no-one knows the private key. However, by default, there is no onchain or offchain method through which anyone could verify that nobody knows the private key.
This still prevents Nicks’ EIP-7702 method from being used for multi-sigs, resource locks, time-locks, etc… since no infrastructure provider can trust the “EOA doesn’t exist” claims made by the user.
- Initialization signature required: Since EIP-7702 is, after all, a way to improve the onchain UX of EVM chains, we need to be very cognizant of the fact that users want one action to == one signature. Since we recover the address from the
authorization
and theninit
the smart account through a protected method (to prevent frontrunning mentioned earlier) - this would require user to separately sign the creation of a the account. - Non portability: The accounts generated by the EIP-7702 + Nicks’ are generally not “importable” into wallets. Since most wallets expect a seed phrase to be imported to derive an account, Nicks’ generated accounts will not have this capability. However, a seed-phrase based system could be implemented with the right industry coordination, this document will explore some basics of this approach.
The good news is that, by being clever with reusing the r
and s
parameters for multiple purposes, we’ve managed to solve for issues i., ii. and iii.!
At the end, a suggestion for an approach to issue iv. will be proposed, but this topic is beyond the scope of this article and solving iv. would require much more effort than other issues.
The Ultimate Solution: Provably Rootless EIP-7702 Proxy (PREP) Accounts
Taking into account all of the benefits of the Nicks’ deployment method combined with EIP-7702 - we’ve dedicated an R&D team to work around the limitations of the method and now - we’re happy to say that we’ve solved for all of the issues while retaining all of the benefits!
The solution is elegant, cryptographically sound and already set for release in our latest Biconomy Nexus smart account implementation! So let’s go step by step:
Multichain front-running protection & initialization with zero signatures.
In order to ensure that the smart account can only be initialized with the initial configuration set out by the user (example of a configuration: a specific EOA owner is the only one allowed to execute transactions) and that no signer can be frontrun, our PREPr smart account implementation expects the hash of the initData
for the smart account to be contained within the r
parameter of the generated signature.
By packing the initData
within the r
parameter, since changing the r
parameter will change the recovered address, we’re making sure that there is only one valid initData
for that specific address. This means that, even if its intercepted, the frontrunning bot will still only be able to initialize the account with the initial configuration that the user actually wanted.
Additionally, since the r
parameter is doing double duty as both the initData
container and the regular r
parameter - by recovering the address from the message - the user is also permitting the initialization of the account itself - meaning that the user doesn’t need to sign anything to allow the initialization of the account since the authorization itself already contains all the protections.
Proving the user doesn’t know the root private key
In order to prove that the user doesn’t know the private key, we’ll use a well known cryptographic trick of replacing most significant bytes of the s
param with some magic value. If the s
param contains enough fixed bytes, the chance that it was generated from a known private key goes down to being basically impossible.
Replacing 13 most significant bytes of s
would require \(2^{103}\) operations to find the associated private key, which would take even the most powerful supercomputers available today around three trillion years to complete. The rest of the s
parameter would be randomly generated.
During account initialization, the exact r
, s
, v
values which were used to encode the creation of the account would be provided within the initData
- the contract would then recover the address, check that the owner set in the initData
is the address recovered from those r
, s
and v
params and check that the s
param has the magic value prefix.
If those conditions are true, the account would set the rootless
flag as true within its storage. Anyone interacting with the account could then verify that the account is actually rootless.
Putting it all together
By combining the hash of the initData
in the r
parameter and the magic value prefix in the s
value and then using it to recover a signer for an EIP-7702 authorization - we have created the ultimate smart contract account!
It combines the best features of EOAs (same address everywhere, purely cryptographic derivation of the address, potential for portability, same configuration on all chains, …) with all of the features offered by smart accounts. With a few simple adjustments, we’ve managed to solve all of the issues of Nicks method deployment.
Not only that, but we’ve also made the deployment of the account up to 80% cheaper than using the CREATE2
method!
On top of it all, since this account uses EIP-7702 to create new accounts - a lot of the tooling (SDKs, bundlers, relayers) can be used both for new PREP accounts and for existing EOAs which were converted through EIP-7702.
An example in pseudocode of setting r
, s
and v
// e.g. set '0xABC...000' as the owner of the account
const initData = "0xInitData..."
// The r parameter is the hash of the initData
const r = hash(initData)
// magic prefix
const magicPrefix = '646d6a0000000'
// s Prefixed with magic value
const s = concat(magicPrefix, randomBytes(19))
// v can be either 27 or 28, it's irrelevant for this method
const v = 27
Biconomy Nexus - The first PREP account implementation
The upcoming Nexus 2.0 account from Biconomy will be the first smart account to support the full feature set of PREP. As more chains add EIP-7702 capabilities to their stack, we’re expecting more and more of our clients to use the PREP account stack to leverage all of the new capabilities.
Nexus 2.0 will be audited and production ready (together with the associated PREP tooling) on Day 1 of the Pectra merge on Ethereum mainnet (planned in March ‘25). As soon as EIP-7702 standard is widely adopted, developers can start reaping the benefits of the PREP standard by using Nexus 2.0.
Nexus 2.0 will support:
- Init block from
r
parameter - Setting the
rootless
flag by checking the magic value prefix in the init block - Lightweight deployments saving up to 80%+ on gas
Conclusion
The Ethereum/EVM developer community has a unique opportunity to set a new standardized account deployment system
Extra: Portable smart accounts
Note: While portable smart accounts are outside of the scope of this article, it’s important to mention portability in the context of creating a new account type for EVM and Ethereum.
The PREP account standard creates a universal, cryptographically deterministic account standard for Ethereum and EVM blockchains. With a bit of additional work, it has the potential to become the default way in which new accounts are deployed as it inherits most of the benefits of EOAs and all of the benefits of SCAs. And it achieves all of this while only requiring EIP-7702 support from chains.
However, there is one feature which EOA users deeply appreciate which is not available by default with this approach and that is portability - the ability for the users to import their account into different wallets by exporting their private key or seed phrase.
While this is often touted by smart account teams as a negative aspect of blockchains, the user behavior points to a different reality. Many institutional users as well as more sophisticated retail users see the existence of the private key and the seed phrase as a core benefit of blockchains. If we are to work towards wider implementation of the PREP standard, there needs to be a way to enable portability.
For portability to work, wallets need two key features:
- Discoverability A wallet needs to be able to find the address of the account from some piece of information provided by the user. With classic EOA accounts this is done by deriving the address from the private key of the user. The private key, in turn, can be derived from the seed phrase. With PREP accounts, we need a different method - ideally deriving from a private key as well.
- Ownership A wallet needs to be able to take ownership over the account which was imported into it. With EOAs this is simple, as whoever can sign transactions with the private key controls the associated address. With rootless smart accounts this becomes much harder as the account can be owned by a much more complex authorization scheme then a simple private key. The biggest question is how to enable the wallet to “take ownership” of such an account.
Out of the two problems, discoverability is much easier. Since the only thing a PREP account needs to derive its address is the address of the initial smart account implementation and the generated r,s,v parameters - those could easily be provided to the wallet to “discover” the account address. By recovering the address and looking at the s
parameters, the wallet could deduce that the account is PREP compliant.
Ownership would need to be solved by allowing the wallet to upgrade the implementation of the PREP wallet to a new implementation. This would be done in a similar way to a wallet putting a new delegation on an EOA which has an existing EIP-7702 delegation from a previous wallet. In order to make these upgrades compatible with things like resource locks - taking ownership over an account could be done with a time delay. Since the PREP account doesn’t have an associated private key, this could be done thorough a standard method on the account itself, which could be encoded into an EIP!
However, as already mentioned - methods for achieving this are beyond the scope of this article and would require broad industry support to achieve. At Biconomy, we’re more than happy to open a conversation with all interested parties on making a portability standard work for PREP accounts and for smart accounts in general.