Native Account Abstraction in Pectra, rollups and beyond: combining EOF, EIP-7702 and RIP-7560
Devcon 7 SEA·Sat, Nov 16, 2024, 09:37 AM · 25:22
Speaker
Account Abstraction has rightfully become one of the most discussed topics in the Ethereum ecosystem. The upcoming Pectra upgrade is set to be the first one to improve EOAs by including EIP-7702. But can EIP-7702 alone achieve "Account Abstraction"? We will discuss the challenges and benefits of EIP-7702, and break down the team's vision for achieving "complete" Native Account Abstraction with RIP-7560/EIP-7701 and how it differs from ERC-4337 + EIP-7702.
Transcript
Hello everyone. My name is Alex. I work on account abstraction and today I will follow your talk with a deep dive into the future of native account abstraction and our plans for it. So for the purpose of this talk, I suggest that we all agree that we want native account abstraction, the way for account abstraction is to enshrine it in layer tools in the mainnet. And we need to answer the following questions before we go into it.
First, we need to know which part of native account abstraction is already happening in the next Ethereum hard fork. We need to see why it is not enough and what is still missing for us to achieve the account abstraction endgame. I want to explain how we plan to achieve it and also explain how other companies and teams can participate in this effort and honestly look at the possible alternatives to doing what we are proposing. So, a quick recap of where we stand with account abstraction right now, if somebody was not involved into it. So, the first account abstraction proposal is ERC-4367.
It solves account abstraction without making consensus changes on the Ethereum protocol. It allowed us, purely out of consensus, to provide account abstraction solution. And it did solve a vast majority of cases. And it has been released more than a year ago. The mainnet and the mempool have been launched.
So it's no longer a new project. It has been used for a year by a very serious project. EAP-7702 is a very important proposal because it's the first time mainnet is getting some account abstraction features. This EAP allows, as you know, EOS to role-play for a time as smart accounts, and it's scheduled for the next hard fork. You have mentioned RIP 7560.
This is our proposal to enshrine the design of ERC-437 as part of Layer 2 consensus, and it has been implemented, and there is a DevNet ready implementation. And now we are also proposing EAP 7701. This is somewhat similar to 7560, but it is trying to be less opinionated using less of the protocol parts and it targets Ethereum layer one, and it relies on EOF to do so. It's an early draft stage, and we request everybody to provide their feedback on it. So a little bit more on 7702.
This is how the account looks for once you update it with 7702. So you still have the private key, but you also have smart contract code. So it changes the behavior of current EOAs, allows them to have code as well. And this fully solves the execution part of account abstraction. Your account can do multiple operations in the same time, do intends, whatever it is.
It does not, however, solve the security part of account abstraction. Because you still have a private key, you still have an EOA, you still have 12 words that can override your smart contract wallet. And there also needs to be another EOA that creates a transaction to use your authorization. The upside of this is that it works great with ERC 4337. And such accounts can be part of account abstraction ecosystem and get gas abstraction and many other features.
So one question you can ask is, great, so next we'll just wait for the rest of account abstraction to be enshrined in Ethereum mainnet. Well, if you look at the specs for the next three hard forks, this is a list of EAPs that are considered or scheduled for inclusion for the next three hard forks, this is a list of EAPs that are considered or scheduled for inclusion in the next three hard forks. This is a long list. These changes will take quite a lot of time. And so if we were to just wait out to introduce account abstraction on layer one, this could take a very long time.
And also, it's a high bar to clear on layer one, this could take a very long time and also it's a high bar to clear in terms of production tested specifications, full spec roadmap, and it requires a unanimous consensus among core Ethereum developers to do such a feature. It doesn't mean that we will just wait for these things to happen. We have a lot of activity we can do on layer tools who are eager to innovate with account abstraction right now. Another alternative is just to keep using ERC 4337 forever. So can we keep using it?
Well, kind of, yes. It's good enough in many cases, but it's very much not perfect. The main downside is it still relies on EOAs to act as bundlers. So you have an account abstraction solution, but you still need EOAs for that. We also create a lot of complexity by implementing a lot of parallel technical stacks, parallel mempools, parallel bundlers and modifications to the node.
And as layer twos want to innovate, they start implementing their own native account abstraction solutions. There are chains who did that. And it is a problem because it breaks the compatibility. And also there are still new EAPs that introduce new features to Ethereum. One big example is inclusion list.
You mentioned Fossil. And these EAPs don't benefit account obstruction users and account by the way. So let's zoom into a flow of a single user operation in ERC-437. So what happens is the user signs and creates a user operation, and the user has to provide it to a bundler server. The bundler server then collects other user operations and bundles them together and provides it as a transaction to the block builder, and it has to use this conditional API, and provides it as a transaction to the block builder, and it has to use this conditional API, meaning that it performs a validation, and he provides a condition for this transaction to be valid.
And then the block builder can include this as a call on chain. With RIP 7560, we make all these superstructures that we had with the bundler and conditional API and entry point contract part of consensus protocol. So it very much simplifies and flattens out the complexity. And for the user, they sign this transaction and they broadcast it to the mempool and the protocol takes care of the rest. And the complexity becomes part of the protocol, but again, it's simplified.
So how it works is that already now, like all transactions that we broadcast to Mempool and include on chain, they have a validation code. However, this code is not a solidity EVM code. It's a, you probably go code that a block builder have. We validate signatures, nonces, balances, gas limits, base fees, and these checks are done in Go as part of consensus, and then the execution is done on the EVM. With 7560, we split the transaction into two parts, and the validation part is also Solidity code that also runs on-chain, but it's still a single transaction that is split into the validation part and the execution part, and error in the validation part means that the transaction is not valid.
It's not included on-chain and reverted. It just cannot be included in a block. So if you're familiar with ERC-437, the most complex possibly path for transaction to take is to have GAZ sponsoring and to deploy a contract, a smart contract, as part of the first transaction interaction. So these are all execution passes in account abstraction. And this is what it looks like in 7560, meaning that for a transaction type, we add a number of fields, and what happens during this transaction flow is first step, user creates a transaction, sends it to the block builder.
As part of a transaction, smart contract gets deployed. Paymaster gets queried if it agrees to pay gas for this transaction. Then the account is queried to see if it accepts this transaction as valid, checks the signature and everything. Then the transaction gets actually executed and reaches the target contract. And if Paymaster wanted to, it gets also notified that transaction execution has finished.
However, what needs to be said, RIP 7560 is not meant to be included in layer 2 in its current form. The RIP process itself was started for features that are common between various Layer 2s, but not necessarily target Layer 1. It provides us a lot of flexibility because we don't need unanimous agreement of all core developers. It's an opt-in process where rollups can decide to pick up features and implement it on the networks and it's very feasible and like logical for some RIPs who get adopted to evolve into EAPs. So what prevents 75-60 approach to being part of the mainnet EAP.
Well, a huge part of it, it defines validation as solidity methods. Like we define solidity methods, and we say that this method has to return correctly, then the transaction is valid. It is a little problematic because EVM is supposed to be language agnostic, and methods are just part of solidity programming language. It's not such a big deal for layer 2s because almost all of them already have some kind of precompiles that are defined fully in solidity and they already do it. Another thing is that EOF, Ethereum EVM object format, introduces the deployment time code validation, and account abstraction could greatly benefit from code validation.
However, without EOF definitions, we would not be able to do it with method selectors. And it can be a problem that your validation code is a part of your contract that can be called by other contracts in some scenarios that can lead to vulnerabilities. So a reminder, in EOF, the contract is being split into parts. So legacy contracts, they have the blob that includes all the code and data of your contract. With EOF, the contracts are split into the header, the code section, and the data section.
What we are suggesting with EAP-77-01 is to also split the code section into parts that have roles assigned to them. So the contract would have an EOF validation code, execution code, any other code, and we can verify the code of the validation section before deploying such contracts. And this code doesn't have to be observable on-chain from within EOF, but it is still executed as part of transaction validation. So if you look again on all the flows, the flow remains exactly the same. It's just instead of calling specific functions, the EVM executes certain predefined sections of your EOF contracts.
And this allows us to get away from these magic method selectors into a more mainnet-level solution. So now it's time to talk about challenges of account abstraction. People have been talking about it for 10 years. It's still not on mainnet. This is because it's actually hard.
If you see somebody talking about validation scope on account abstraction you immediately think about this picture and the main problems for that account abstraction creates is the cross dependencies between transaction and validations and the complexity you get in building blocks efficiently and maintaining a decentralized peer-to-peer mempool efficiently. So let me try to explain these problems. So the cross-transactional dependencies look like that. You have transaction 4. It modifies the state, and it makes the transaction 5 invalid.
So when you receive the transaction 5 individually, it seemed valid to you because A was equal to 0. But now you started building a block, you include transaction 4 first, and now A equals 1 and it's not a valid transaction. And in order to work around this issue in general, we just have to split the transaction into two parts and have the validations run separately from executions in their separate place in the block. So these are still three account abstraction transactions, but their validation parts are separated from them and they run before any execution code starts running. Now you may ask, but what if validations invalidate each other?
What if the validation code changes the state that another validation uses? And in general, it would be possible. And in order to prevent that, we need to sandbox the validation code to prevent it from doing certain things that it should not be allowed to do. So what are those things? It's accessing other people's storage and accessing environment opcodes.
So environment opcodes are block number, timestamp, base fee, everything that may change from validation and execution or between phases. And other people's code is code in other contracts unless it is in a mapping mapped to your address. And on layer 2s, it's also any stateful precompile. So doing this is illegal. All other things are allowed in validation.
And it allows us to do many great things. You can use tokens, you can transfer tokens, you can do all of that in validation functions. There are other small complexities. One example is you don't need to invalidate a transaction to make it hard for a block builder to build a block with account abstraction. One good example is unused gas and using unused gas as a vector.
For example, you're building a block, you include five transactions, you see that you still have a lot of available space because transaction four requested 10 million gas limit but didn't use it, so you start adding another transaction to your block. And what happens is, transaction four saw the change in the state and started using more gas. And now you are, like, you have a recursive,-and-egg problem because now the transaction 6 doesn't fit your block and you need to exclude it. And you can get to square one. We do solve it by introducing a gas charge on unused gas.
But I'm just using it to showcase the kind of problems we need to solve when implementing account abstraction natively. And another thing is maintaining an efficient mempool to receive a huge number of transactions simultaneously and validate them. You need to parallelize their validation. So assume, like, here's a block builder. It has six CPU cores, and it's performing validation of six transactions in parallel.
So it runs them individually, meaning they don't access each other state. And if it finds a transaction that is not valid individually, it gets included from block building. And the next step for the block builder is to validate all transactions that are remaining in its mempool and build a valid block. If we were not able to separate the scope of validation code in one of these transactions, what could happen is we could have a mass invalidation event. When one transaction changes some state and makes all other transactions in your block invalid.
And it provides a huge DDoS vector for mempool participants and block builders. Because we don't want them propagating invalid blocks. Now, developers who are interested, especially if you're working on layer 2s, what can you do to make native account abstraction happen? First, do get in touch with us on any of our channels, Discord, Telegram, and let's talk about native account abstraction. Do just read and get familiar with either both RIP 7560 and EAP 7701.
We are looking for feedback on it. And you can also dive into the code. This is a link to our reference implementation of RIP 7560. There is also a roll call event for the RIP process. I guess everybody knows it.
Just join it, add RIP 7560 to the agenda and discuss it with other layers too. And let's start building it. So here are our websites and that's it for now. Thank you. Thank you so much, Alex.
Let me start with questions. The first one is if 4.337 bundlers don't yet support the aggregation portion of the spec, how can we be ready to make it part of the protocol? Yeah, so aggregation is a part of 4.3.
3.7. It will be part of native account obstruction eventually. We have a draft EAP for that. However, it's a complex topic in itself.
The aggregated signatures are complex, and there has been little adoption of aggregation yet. It does provide additional challenges in the context of native account abstraction, but I think we will overcome them. And again, our approach is to make all these changes very, very modular. We don't want to make one mega account abstraction spec and implement it in one fork. We want to make basically as many EAPs as possible, reasonably, so the chains can adopt them meaningfully, but one by one.
Next one, how critical and how centralized is the bundle? Are the bundled? Is the bundled? Can I see? Sorry.
How critical and how centralized is the bundled? I guess the bundler. So in ERC-437, bundler is critical. Not very centralized if you use it correctly. So if you're using it as a mempool, that is not like...
You don't depend on any centralized bundler. With 7560, the role of the bundler changes, it becomes more of an assistant to the block builder, and then it's as decentralized as the underlying network. There is no added decentralization vector on the bundlers. Does that make sense? Yeah, okay.
Thank you. Next one, we have 433775607702. Can you describe how they all play nicely with each other and how can we avoid once again fragmentation in this space? In this case, with regard to account abstraction solutions. Right.
So 7.7.0.2 does not pose any fragmentation challenges whatsoever because this is just a new feature of the EVM and I assume it will get supported pretty widely and it's also an addition to account abstraction roadmap. With 467 and 7560 we keep the user flow so similar that it can have very minimal friction in terms of fragmentation because if you have two accounts and their differences are so minimal, I assume just most wallets would support both and both of them will coexist peacefully for a period between now and when 7701 is implemented on mainnet.
And so they are all still part of the same ecosystem, so it's not fragmented. It's just different flavors of the same thing, if that makes sense. What's your recommended roadmap for MetaMask to achieve the end goal of account obstruction? Yeah, so MetaMask and other wallets, UA wallets, it would be great if they started looking into account abstraction. They can start with 7702, with getting all users to also include some kind of code in their EOAs.
It can be very simple, like recovery or gas sponsoring and everything, but crucially it will get a production experience of having and managing a fleet of smart contract wallets because up until now, most wallets have only been managing the private keys part and did not look at users' wallets as smart contracts. And after that, there is no reason for MetaMask not to use ERC4337 wallets. For people who are starting now, you probably don't need to steer them into using 7702 if they are newcomers. You can just get them to deploy an upgradable proxy smart contract wallet. And as long as it's an upgradeable proxy, they can evolve together with account abstraction, like versioning and all that.
Right? What do you mean by other code, in brackets, section at 7701? Yeah, this is referring to this slide. I don't have slides. So you can have any number of code sections in an EOF account.
So any code that does not have a role assigned to it, as we described it, is just an external code, so it can be called by, like, other contracts or other addresses can just call into this code and if the code is assigned a role you cannot call into this code it has to be executed as part of a eap 7701 transaction right it's uh so this is the difference between like other code and a code with an assigned purpose in terms of account obstruction. Now, the last question. What's the point of separating validation and execution in a theorem's account obstruction if conflicts can still arise during execution, even after validation under restricted rules? Yeah, great question. The problem is if the execution conflicts with each other, you can get a state you didn't initially want.
For example, you can get a transaction to revert, but the transaction is still valid. And another thing is execution is not limited, not sandboxed. It can be a 20 million gas operation, and it can write all the storage in the world. Validation is limited and sandboxed. So we extract all the validations because we assume they are small functions, relatively, like I don't want to say pure, but clean functions that only access accounts on storage and if they were to collide that would make block invalid.
The difference between the reverted transaction in block and in the valid block is the difference between a block builder being DDoSed and somebody having to redo his action.
Automatic transcript — names and jargon may be misspelled.