# Understanding EIP-7002 and EIP-6110

- Speakers: [Lucas Saldanha](https://streameth.org/speakers/lucas-saldanha), [Stefan Bratanov](https://streameth.org/speakers/stefan-bratanov)
- Channel: [Devcon 7 SEA](https://streameth.org/devcon_7_sea)
- Date: 2024-11-12
- Duration: 24:56
- Watch: https://streameth.org/watch/67330efd3a168eb535f36fc6

## Description

The first part will be an overview of EIP-7002, explaining how it works, why adding this extra option to exit validators is important, and addressing some of the UX challenges of this approach. The second part will be a technical overview of EIP-6110, explaining the UX improvements for validators depositing on the beacon chain, the removal of pre-merge technical debt as well as a quick look at the EIP implementation in Teku.

## About the speakers

### Lucas Saldanha

Lucas is an Ethereum enthusiast and passionate about protocol development. He has been working at Consensys for the past seven years as a protocol engineer. Lucas has worked both on Besu, an Execution Layer client, and Teku, an Consensus Layer client.

### Stefan Bratanov

Ethereum core developer working on Teku


## Transcript

It is bright. Okay, so, yeah, I'm Lucas and I've got Stefan here with me. Our talk was originally designed to be two talks, but do some scheduling things. We had to merge them together. So, well, we'll do our best to make sure we go through the content and everyone understands everything. So, yeah, I'll start with my part and then we're going to have Stefan. Thank you, Stefan. Okay. So we're going to start with EIP7002, execution layer triggerable withdrawals. Before it was named execution layer triggerable exits, but there are some updates that we renamed it ZIP. Before talking about ZIP, I want to go through a little bit of a context here. I'm assuming that everyone is aware that in Ethereum we have validators, and they are staking 32 ETH, and then they're performing the duties like voting for new blocks with attestations, proposing new blocks, and things like that. And well, when you're creating a validator, maybe everyone knows that, but we have two sets of credentials. You have your validator key, which is associated with your validator public key, which is used for signing your blocks, signing your attestations and everything. And you have your withdrawal key, which is kind of represents the ownership of the staked amount of ETH. Another concept is solid staking versus delegated staking. So this is kind of a different thing. Like staking is staking. But I think solid staking will be kind of the most basic thing when you think about staking. You know, you have a laptop. You create a validator, you have the validator key, you have your withdrawal key, so you own kind of everything. And when it comes to delegate staking, there is like a bunch of different arrangements. You have custodial, noncustodial. But for this exercise, let's just assume that you own the withdrawal key. Someone else owns the validator key because they're running your node for you. But they do need the key because they're going to be signing the attestations and everything. So they need the key. So that's just to do with that. Okay. Another thing before we jump into the EIP, I want to touch on voluntary exits. So voluntary exits since phase zero has been pretty much the same. If you want to exit the validator, you don't want to stake anymore. You will send a signed voluntary exit message, but that message is signed with your validator key. So you sign that message, broadcast it through, send it through the beacon API. It's going to be propagated in the network, eventually included in a block, and after some time your validator joins the exit queue. Pretty straightforward. However, as you can see in the diagram here, if you don't have the validator key, you're kind of in trouble because you don't really have a way of exiting your validator. You need to kind of ring your operator, hey, could you please exit my validator for me? Well, if they are nice people, they will do it for you. But, you know, it's kind of like a grief attack vector because technically the node operator can, like, not really do their best job when doing the decisions and everything. And they have ways of, like, slowly chipping away your stake, which is not great. There are ways around this. Some of the operators will give you a pre-signed exit message when you join the system. So you keep that message safe whenever you want to exit. You already have the signed message and then you can exit. This is a workaround because there are a lot of complications with this. There's a lot of, you know, you need to keep that message safe. You don't you're not 100% sure if that message is going to work. And they have to have all the infrastructure around managing that message and everything. So it's, yeah, it's kind of a hack. Well, back to the problem that we're talking about. You can only exit your validator today with your validator key. Right? And the solution is easy. Just allow both the validator key and the withdrawal key to exit the validator. Yep, it's pretty straightforward. Unfortunately, implementing it, it's not that easy. And that's pretty much the context on how we get to EIP 7002. So, why it's not easy? It's important to remember that when it comes to the consensus layer and the execution layer, the consensus layer doesn't have a complete view of what happens on the execution layer. So it's got a limited amount of information that comes through that side. I think a good example of this is if you think about deposit processing. Stefan is going to be talking a little bit about it later. It's a complicated mess. It's a whole system, keeps updating and fetching information. It's not that easy. So what we really need is we need a mechanism to create a message on the execution layer, send that message all the way to the consensus layer, but that message has to be authenticated with an account on the execution layer side, but at the same time, all the authorization happens on the consensus layer side, because the consensus layer is the one that knows who is the validator, what is the withdrawal credential associated with that validator, what is the balance, and all this kind of stuff. So that's kind of the thing that we're trying to solve here. And that's pretty much the idea with withdrawal requests. So it's a request that comes from the EL, goes to the CL, and it's got pretty much three pieces of information. One is the source address, which is supposed to be the address that you have set as withdrawal credential on your validator. The public key, which is basically what is the validator you are sending this request to. And the amount, which is an interesting one. So before we didn't have the amount. So the amount was introduced because after EIP-7251, if you guys were here to listen to post-talk on MaxEB, now it's possible for validators to have more than 32 ETH balance, right? So technically you can have a validator with like 1,000 ETH or something staked. So we basically split the withdrawal into two different types of withdrawal. You can do a full withdrawal, which means I want to withdraw every single way that I have staked, which basically translates into an exit. Or I want to do a partial withdrawal, which means, well, you know, I have 100 ETH. I want 50 back because I want to buy a new car or something. So you do like a partial withdrawal. You get it back into your account, and then you can use the money. And we use the amount field for that. So an amount equals zero means a full withdrawal, which can be a bit weird to think about. And an amount greater than zero is like a partial withdrawal. I just want to withdraw part of my stake. Hopefully everything makes sense until now. And on this diagram, I'm trying to capture how things have changed compared to the previous diagram. So the way that we're creating this mechanism is basically now we're going to introduce this withdrawal request smart contract on the execution layer side. And that contract has pretty much two functions. So the first one is a function that the user is going to call to basically create a request. So when the user wants to create a request, I'm going to send a transaction, signing it with my withdrawal key, not the validator key, and the control is going to look at it like, oh, okay, that's cool. Someone's creating a withdrawal request. It's going to set that address as the source address on the request. And I'm going to be on this request here. We pass two pieces of information, the validator public key and the amount. Eventually, the execution client is going to call the contract and read the information for it, read the request that are on the queue. The queue is on the contract state. And send it over to the Beacon node through engine API, and I'm not going to go into a lot of details of that because, again, not a lot of time, but basically whenever it's time to create a block, the Beacon node is going to receive those requests from the EL, some verification happens and everything, and then the authorization part happens on the consensus side. It's going to look at the request, make sure that the source address, so the account that is sending this transaction here matches the validator on the consensus side and some other rules, you know, make sure that you're creating a request for the right validator and everything. Cool. So hopefully this makes a bit more sense. One interesting thing to note here, and that was actually probably half of my original talk is that when you look at this kind of orange area here, you can see that this mechanism for sending requests from EL to CL can be quite useful for a bunch of different things. And yep, we did notice that. And that's why we have EIP 7685, which introduced this concept of general purpose execution layer requests. So now we already have all this mechanism for creating different types of requests. For the next fork vector, we already have three types of requests. We have withdrawals, the ones we were just talking about. We have deposits, the one that Stefan is going to be talking about. And if you were here for the previous talk, consolidations, it also happens through an execution layer request. So that was kind of the most interesting part of this system. So take a look into that because it's pretty cool. Before I finish, I just want to go through a few caveats because there's no free lunch. There's always something that you need to give away. So the problem with request and kind of the execution request in general is that creating a successful transaction on the EL side, like creating a request, doesn't guarantee that that request is going to be successfully processed on the consensus layer side. I know it sounds a bit weird, so the user experience is a bit clunky. You kind of need to look at the consensus side, make sure that everything works out, create the request, and just kind of hope that nothing's going to change in this in-between. Hopefully it's not going to be too bad, but it can happen. And another interesting thing is if you currently have a validator and your validator has a contract address set as withdraw credentials, well, things are going to be a bit more complicated. For those of you who are familiar with the EVM, the contract that is creating the request is not looking at the transaction sender for authentication. It's looking for the message caller. So that means that if you are interacting with the request contract using a smart contract, the smart contract address is going to be the one that's going to end up on the source address. So for this whole thing to work, your validator with your credentials has to be the contract address, not the account that is sending the transaction. So again, I'm sorry for you if you're in this situation. Hopefully if you have an upgradable smart contract, you can get away with it. You can use delegate calls and do some very smart stuff to make it work. That's not my expertise. I'm not going to talk too much about it. But there is a way for you. Just keep that in mind when you are looking into this. One important thing is that this does not replace voluntary exits. Voluntary exits are still the easiest way to exit your validator. If you have the validator key, you sign the message. It's going to be broadcast to the network. It doesn't cost you gas or anything. There's no transactions involved. So, yeah, keep doing that if you can. But this is basically like a way of kind of filling that gap that we have on those scenarios where you don't have your validator key. And quickly before I run out of time, I just want to mention that withdrawal requests are different from withdrawals in the sense that if you guys remember Capella, that's when we introduced withdrawals. A withdrawal request can eventually generate a withdrawal when you're doing a partial withdrawal. But they're not the same thing. Just because you have the terminology and things like that. Okay. That was a lot. Hopefully enough for people to understand. I'll leave it here and then I'll hand over to Stefan for his part. Thank you. Oh, thank you. How does that work? Yeah, Next slide. . Okay. Hello. So I'm going to talk about EIP6110, which is supply validator deposits on chain. And you may wonder what this EIP is about because validator deposits are already on chain. But the keyword here is supply. So essentially, this EIP changes how the deposits made to the deposit contract, which sits on the execution layer, how these deposits are supplied to the consents layer, where either a new validator is initialized or an existing validator balance is topped up. So I'm going to start by explaining briefly how the current deposit processing works. And then I'll go over the depositing processing after this EIP, which will be part of the next fork. Yeah. So current deposit processing, basically a user submits a transaction containing deposit data to the deposit contract, which is essentially 32 if. And users usually do that via the staking launchpad. And then there is this eight hour delay where the consensus layer has to consider the state of the deposit contract and this has been designed to be 2048 blocks when with proof-of-work blocks which are which were around 14 seconds. And this was done to ensure that if there are any issues with if one, then essentially that wouldn't impact the beacon chain. And eight hours was just it gives about enough wiggle room to ensure that any issues are fixed. And then there is a voting which is a 64 epochs. And it's kind of, this is like off protocol consensus mechanism. It was designed before the merge. And basically it ensures that validators agree on the state, on the same view of the deposit contract, which sits in the EL. And before the merge, basically the EL is driven by proof of work. So there was no real connection between the execution layer and the consensus layer. And then this voting, basically, it finishes when at least half number of the votes are the same. And after that, proposers include those deposits alongside the block. And then all nodes can verify these blocks. And then a valid deposit basically either creates a new validator or it tops out with the balance of an existing validator. And this is a diagram of the current process. So you can see this user. He basically does a deposit transaction, uses the Stenky launch pad, and then the important part here is basically you can see on the right the beacon node, and it has this chunky EF1 module which constantly pulls the EL via the JSON RPC API. And it does that 2048 blocks constantly. In order to build the Merkle tree, which then can be used to produce proofs, which are included alongside deposits. And this is the current process, which is still Ethereum works like that, even though we have already migrated to proof of stake. We still use this JSON RPC. And the way this, the EAP6110 works is it simplifies a lot. Basically the same deposit transaction is made, but then the deposits come directly from the EL via the engine API, and they're included in blocks, and then they're processed on finalization of the chain, which is currently around 13 minutes. And then the same flow, again, the same thing, a valid deposit will either create new validator or top up an existing validator. And the diagram now looks like this, which is pretty much what Lucas showed. You basically have the execution requests. And now you get the deposit request over the Engine API. So whenever a proposer proposes a block, they get the deposit requests. And basically, this whole EF1 module, which was quite quite chunky now it's no longer part of the beacon node. So this is the diagram. And to quickly summarize the advantages of the EIP, basically there is nowadays a delay of around 11.4 hours before your validator is added to the activation queue. And this is basically the follow distance, these 2048 blocks, which is around eight hours. And then there's this voting of around 32 epochs, which is 33.4 hours. And now this is reduced to just around 13 minutes or two epochs, which is 33.4 hours. And now this is reduced to just around 13 minutes or two epochs. And another advantage is the increased security because we no longer rely on this off-protocol mechanism. Now we just inherit the security of the chain. And also there is another benefit because currently we have this deposit contract snapshots which basically are a Merkle tree up to a certain point in time. And we no longer need this because we no longer need to provide proofs because we are just getting the deposits from the engine API. And one other benefit is that we no longer rely on the JSON RPC API. We only rely on the engine API. And it's also we just no longer need that very legacy and brittle part of the CL client's code, which is always good to delete stuff. And one more slide I wanted to show, I wanted to quickly show that this EIP is actually not, it's actually simple to implement. So if you're interested, you can go over this link and see how we implement it. We generally try to do small PRs, so it's just eight PRs, but it's not big changes. So if you ever want to check how an EAP is implemented, actually, this is a good one to go over because it's quite simple. Yeah, and that's it, pretty much. Thank you pretty much. Thank you, thank you. We're going to get to some questions now. And again, if you're new to seeing a talk today, scan the QR code, add your question, and you can vote. If there's one that's already there and you would like to see it answered, just to make sure it gets answered and pushed to the top of the queue. Thank you, thank you. So we will start with why a valid request from the execution layer would be rejected on the consensus layer? I can probably take that one. It's hard to go through all the different reasons why. I think the best way of thinking about it is that I like to separate that the EL is doing the authentication side of the request and the CL is doing the authorization side of the request. So I think the easiest example that I can think of, for example, for withdrawal requests, let's say that you create a request for someone else's validator. So the transaction is going to be successful. The request is going to be added to the contract. But when the CL receives that request, it's going to try to match the source address with the validator with your credentials. It's going to say, well, you don't really own that. You can't really do that. So that's one of the reasons. Yeah, there are other more specific rules that can, but I think that's probably the easiest way to think about it. The EL doesn't really know the business rules on the CL side in the same way that the EL can't really validate beforehand that that's the right validator. So that's kind of part of the reason, hopefully. Yeah, that's it. Thank you. part of the reason hopefully yeah that's it thank you and it looks like we have another one for you right again so why do you think contract address as a withdrawal credential is a caveat um it's it's more like it's a more complicated thing because um there are two problems with this one is that the currently the validator withdrawal credentials cannot be updated. So once you... I didn't really touch on the whole BLS credential side of things, which is something that already was there before. But the way that it works right now, once you set your validator withdrawal credentials to one address, you can never change that address. So a few problems happen here. The first one is, as I mentioned, if you have your validator credentials set to a contract address that is not upgradable, you're never going to be able to update that code to call the request contract. So you're already kind of locked out from this mechanism straight away. If you have an upgradable contract, you can write some code to kind of get around it. So it's more like a caveat in terms of something that people need to get their heads around and make sure that they consider when they're implementing. Because I think the natural thing to think is, well, I'm going to sign the transaction with this credential, with this account, sorry, key, and that's the one that's going to show up on the request. But that's why it's kind of a caveat. Thank you. All right. Now for you. If EIP-6110 makes ETH1 vote legacy, do we have to carry all ETH1 voting fields and logics in consensus layer, even in post-Electra? Yeah, sure. So there is a little bit of transition period when post-Electra to transition to the new way, because we still have to process deposits by the old way for some time. But after that is done, we can pretty much remove all of this legacy code in next releases after the fork. Thank you. Is there a proof generation process to withdraw, similar to performing Eigenlayer withdrawals? Unfortunately, I'm not familiar with eigenlayer withdrawals? Unfortunately, I'm not familiar with eigenlayer withdrawals process, but there's no proof generation on this withdrawal. Hopefully, if I understand the question, there's no proof generation. What if a deposited request failed? Will users' ETH be refunded? So, when you deposit ETH to the smart contract, there is technically no way a deposit request fails. So if the deposit request fails, that means that there is like a consensus failure, which, yeah, it wouldn't be refunded, but it's a big issue. All right, I think we have time for one, maybe two more. How resilient is the engine API comparing to JSON RPC API? Yeah, so the engine API basically drives the execution. The consensus layer client drives the execution layer client via the engine API. So it is very resilient. The JSON RPC API can... It's not... It's still very reliable, but it is not critical. So there could be some implementations in some clients which are less reliable than the engine API, which is very critical. Awesome. And we have just about five seconds left, so probably not enough time to get to the next question, but if you'd like to come up to the speakers and ask them questions later, they'll be sticking around for a little bit. So thank you very much. Let's have a big one.
