# L1SLOAD in Action: Write L2 Dapps that Read from L1 State | Devcon SEA

- Channel: [Devcon](https://streameth.org/devcon)
- Date: 2025-10-07
- Duration: 1:24:15
- Watch: https://streameth.org/watch/yt-FhvJPUcD6go
- YouTube: https://www.youtube.com/watch?v=FhvJPUcD6go

## Description

In this workshop we will explore some interesting new use cases unlocked by the newly proposed L1SLOAD precompile (RIP-7728). We will develop and deploy L2 dapps that read from L1 state using this precompile.

Speaker(s): Péter Garamvölgyi, RH
Skill level: Beginner
Track: Layer 2
Keywords: Developer Infrastructure, DevEx, Rollups

Follow us: https://twitter.com/efdevcon, https://twitter.com/ethereum, https://warpcast.com/devcon
Learn more about devcon: https://www.devcon.org/
Learn more about ethereum: https://ethereum.org/ 

Visit the https://archive.devcon.org/ to gain access to the entire library of Devcon talks with the ease of filtering, playlists, personalized suggestions, decentralized access on Swarm, IPFS and more.

Devcon is the Ethereum conference for developers, researchers, thinkers, and makers. 
Devcon SEA was held in Bangkok, Thailand on Nov 12 - Nov 15, 2024.
Devcon is organized and presented by the Ethereum Foundation. To find out more, please visit https://ethereum.foundation/

## Transcript

lunch uh you will need some brain cells to to follow along uh although overall it's going to be kind of a beginner friendly uh Workshop we're going to do kind of a presentation first and then some solidity coding if you have some basic experience with solidity with smart contracts or if you're just uh you know comfortable just reading code then you should be able to follow along um so yeah my name is Peter I'm a Procol engineer at scroll and today I won't talk about scroll per se but I will talk about a new proposal uh that we proposed called RP 7728 l1s load so this is a new proposal that scroll kind of um implemented in a devnet but we hope that this will be adopted by multiple l2s in the future so the hope is that uh after this initial 20 minute presentation you kind of get the idea like what is l1s load what can you do with it uh why should you care about it and then for the remainder uh myself and my friend RH will uh do like a solidity kind of Workshop so we have a two Hands-On examples and exercises for you okay so now you can hear me uh I haven't said anything important yet so uh yeah let's kick off oh by the way before we kick off um if you have any questions feel free to interrupt me but also there is this uh Q&amp;A function here in the app so you can just click here I think most people probably don't know don't know about it I don't think it's widely used feel free to submit any questions here as well I will keep an eye on this all right so l1s load is a new proposal for rollups uh for l2s it's a pre-compile that allows developers to build applications that read L1 state from their L2 contracts we hope that this is a new functionality it's uh not groundbreaking this is something if you're very technical or if you take on the cost you can already do in your dep uh but this proposal makes it much much easier and we hope that this will unlock a lot of new applications so I want to talk about what is Ion slot kind of show you the interface how to use it what are some of the use cases that we found so far uh then I want to get a bit more philosophical like why do we want to offer this service on the protocol level and finally just some insights into kind of the Procol engineering part and the challenges of Designing such a such a proposal uh there's going to be another Tok on Thursday where I will jump into much more details about these Procol level uh considerations all right so what is L1 s load so L1 SL load as I mentioned is a pre-compile if you're familiar with the evm you know that there's the evm bite code uh that you execute but there's also special contracts called pre compil that uh Implement certain functionality on ethereum on layer one this is usually like heavy you know expensive cryptographic operations that would be very uh expensive to implement in solidity but we can also use the same mechanism to expose other functionalities to to L2 smart contracts so L1 Lo is a pre-compile and you can call it from your contract just normal solidity code and you can read State directly from layer one which is ethereum um this is how it looks how many of you are familiar with solidity or has written solidity okay so I think you should be able to follow along uh basically this is just a very intro example the way you would interact with any pre-compile including m1s load uh is basically you can just issue a call to it like a smart contract call uh here we use a low lower level call called Static call and you just encode uh the the payload and with this proposal the payload is simply a contract address an al1 contract address and one two or more storage Keys you can call it from your contract um and then you can decode uh the result so this is actually fetching data not from the local blockchain that you're running on which might be scroll it might be optimism it might be arbitrum any L2 that implements this proposal uh it's instead of that it's fetching data from ethereum L1 uh under the hood so this is defined in a in an rip I'm not sure if any of you are familiar with this so EIP ethereum Improvement proposals are used to uh you know propose new features for the base layer for ethereum and there's kind of a new initiative this year called Rip which is similar process for rollups so rollup Improvement proposal it's uh optional so we can create these proposals if you guys find it useful then hopefully more and more RS will adop this yeah so just more details here uh why do we care about this why is it useful this is kind of as you say it's kind of low level just looking at the previous slide code example it's kind of hard to see what what it's used for luckily we've already run a couple of hackathons and hackers came up with some great use case ideas in the past few months and I think we have a similar hackathon just after Devcon one of my favorite use case examples was cross layer tornado cache Bridge so many of you might be fam familiar with tornado cache it's a shielded pool basically you can uh deposit your assets and then withdraw to another address and you cannot correlate the depositor and and withdraw address so it's a privacy preserving mixing pool uh but you can only you could only use it on L1 but you could use the same technology to kind of deposit on L1 and rraw on L2 uh and this could be built using l1s load another use case is ens so ens is still primarily used on layer one uh although they are exploring you know supporting more and more l2s or deploying on l2s but if you're on a chain that doesn't have enss then through l1s load you can still resolve these domains uh just by reading the register uh contents from i1 there's also cross layer reputation system incorporating data both from L1 and L2 chains uh there's bunch of defi application use cases so for instance uh you could borrow on L2 without Bridging the collateral to L2 just using your collateral on L1 that's an idea that they explored uh you could also Implement these hooks for UNIS swap to make sure that the L2 uh pool has enough liquidity and and not too high slippage compared to the L1 pool so kind of give more assurance is to to you when you swap and you can also use other you know multi a wallet key store uh use cases with this uh so these are just some highlights and I linked all of them here you can check the slides if you're interested these are very interesting project that we've seen at he hackathons all right so now you kind of have a general idea of what is1 LO so uh let me jump into kind of why we want to provide this function on the protocol level I wanted to give a quick walk through of rollups but I think many of you were here for the previous session by Emily and I prepared two slides and Emily did like 50 slides and she did a great job kind of telling all of you what rollups are so I'm just going to keep it very short so a rollup is an ethereum that's uh inheriting a lot of security guarantees uh from L1 which is ethereum in the case of rollups so rollup create an L2 chain and then package these L2 blocks into blobs post it on ethereum and also post the execution results which is the L2 State rout and then there's different mechanisms how you can verify the out2 state root towards a canonical Bridge so you can use fra proofs you can use ZK proofs there's different pros and cons so if you think about information relay between L1 and L2 uh when you relay information from i1 uh you need to uh usually use a deposit message or some kind of other message on in the canonical bridge and this message will be relayed by the sequencer uh in a in a verifiable way so uh the sequencer would include these deposit messages where you can encode additional information but uh the sequencer could also Implement other functionality for instance relaying the Alon block hashes the other way around you usually need to First submit a withdraw message on the rollup and then once this is finalized you need to claim it on the a one side so uh slightly different ways uh depending on which direction you want to go all right so if you're a dep developer and you want to read some data from L2 on L1 how do you do that well you're lucky because you already have the L2 State root on L1 that's kind of an inherent property of or rollups that the L2 State rot is postate to L1 so your contract can just read the state root and provide a miracle proof and then you can verifiably read any state from L2 the other way is basically the same thing but uh it's a bit trickier because l2s usually don't have this notion of the i1 state Roo uh so we would have to implement that first but there's ways around this to implement it and then it's the same thing you provide a miral proof to read from i1 so it is already without this proposal is possible to do it but it's not very convenient like how do you relay the album stage rooot how do you verify it how do you provide this meral proof it's a lot of extra complexity and overhead for the developer as well as cost so the the idea here is all of this process the second part how to read L1 state from L2 is something that the sequencer could provide you as a service so hide all the complexity from the developers and you just focus on your application logic and just interact with this uh contract so I would say it's Miracle proofs as a sequencer Service uh that's one way to think about it uh if you think about this how how it's implanted by the sequencer basically any call to this pre-compile is translated to an RPC call to an L1 note so if you're familiar with the uh Jason RPC of ethereum there's one called e get storage at that's basically what this pre- compa response to uh and then the tricky part is how do you verify it so uh we also need to make sure either in the fraud proof or in the ZK verification proof uh that you also verify this that the sequencer didn't cheat you the sequencer actually relate uh the correct message as an aside many of you might not know like why do why do we use a pre-compile why don't we use an OP code for instance uh it's mainly because of compatibility so we want to maintain compatibility with existing tooling with the evm you know solidity compiler if you had the new OP code then none of the tooling knows about it but if you add the new pre-compile then most of the tooling can interact with it as if it were you know a normal solid solidity contract so it's a much less invasive way to add functionalities that ethereum might not have all right just a little bit more details about kind of the implementation U because as myself Procol Developers for rollups and other rollups team rup teams you need to think very hard about how do you implement it what are the possible attack rectors that this could open up how do you verify the inclusion Etc so the interface of the contract uh that you will also see in more detail in the solidity example is we try to keep it as simple as possible so basically you just need to pass an address and then one to up to five in the current spec uh storage key so you can read up to five storage values from L1 in a single call to this pre compile and then the result is also just standard storage slots if you're familiar with storage layout then you know what this means if you're not then RH will tell you all about it uh in a couple of minutes uh it just return to you and then you can decode it uh implementation wise there's two main prerequisites that might be a bit controversial so first I briefly mentioned that you need to have this notion of what is the latest L2 L1 block hash your L2 needs to have this notion so uh either the sequencer needs to uh relay this with a special system transaction or you need to have some other mechanism but all the L2 NOS must agree on this otherwise your execution would diverge so I would call this feature trustless L1 block hash relay some rollups already have this others have designs for this but not launched yet in scroll the way it would work and this might be different or similar to other rollups is the sequencer optimistically relays this information uh but any other note can very it at this point so if the sequencer cheats then it's easy to detect and when we finalize the batch with the ZK proof that's when we verify that the sequencer actually relates the correct block hash because on L1 during finalization we have access to this information and the second prerequisite is that for reading L1 State you have you need to have access to an L1 node right uh which is already true for sequencer so sequencer has to process these Bridge messages so they already connect to an L1 node but currently for some l2s you don't if you run a follower node you don't need to connect to an L1 node now if you adopt l1s load proposal then you must always connect to an i1 node so that might be an additional overhead for some uh node operators but I would argue that this is kind of acceptable yeah so all add to nodes then must connect to an1 node so that they can serve these requests uh about i1 State and then just two more notes about implementation so we have a reference implementation I have a link to this uh in the slides if you're interested in our go ethereum Fork but basically what you need to do is pretty simple so you need to modify the evm and add this pre-compile so that when there's a call to that address which is specified in the rip then it triggers execution of this special contract and when this contract is called it simply starts executing an RPC request against the L1 node and waits for the result so there's some complexity here that I probably won't go into too much that like what happens if the request time times out or the request fails uh this can be an issue and also this request might affect throughputs but normally when you run your L2 node on the same machine let's say or in the same data center as the L1 node this should be fairly fast and and error free and once the RPC returns you return these results to to the evm and execution continues as before so that's the execution part and the second part is verification uh as I mentioned we need to keep relaying these L1 block hashes to to L2 in a very viable way so in our case at scroll for instance we have a solidity contract on L2 the only thing that the sequencer does is that it takes the L1 block headers and feeds them into this L2 contract and the L2 contract actually does the verification that it's a correct chain of L1 blocks and then once you submit this to L1 and verify it in ZK proof then we read the the block has the correct block has from the L1 you know evm context and verify that this relay step was done correctly and finally so this first and second step is the uh trustless block hash relay component but you also need to verify each and every call to this l1s load pre-compile so for any precom by call we need to or the sequencer or the prover depending on your architecture it needs to fetch an MPT proof and it needs to verify that as part of the broader ZK proof so this is something all of these steps are steps that you would need to do as a developer uh but now that this is part of the protocol and it's a sequencer service you don't need to care about this anymore you can know that it's it's working and verified all right uh lot of details just a few more uh notes about the next steps so this RP is fairly new we just published it in June this year uh there's a call for the RP process called roll call we presented it in July and then as I mentioned since July until now we had a bunch of hackathon where hackers and and devs could explore this and play around with this proposals and for now we just want to continue this process and we'd love to hear more feedback from developers from uh Procol maintainers uh basically once we can converge on a spec that that everyone is happy with and L2 other L2 teams at least two or three L2 teams uh have some willingness to adopt it then we can finalize a spec and and start rolling rolling this out in production I think it would be awesome to get to that stage uh next year all right there's a few additional resources here for your reference uh and I have again the slides here if you want to save them but for the remainder of the the talk or the workshop we want to jump into more like hands on coding before we do that any questions yeah yeah so when you have a transaction that calls i1s load then any node be it sequencer or follower node will execute an RPC call corresponding to this pre- compa call for the validation yeah so proving it depends on your proving system but I think we we can say that uh so the question was how long does it take to verify the whole thing uh a couple of years ago this would have been impractical because you couldn't have proven you know an L1 MPT proof in ZK the techn technology was not there yet but now proving speeds have been catching up and you have you know general purpose zkm so in our experience this would add maybe a couple more minutes to the proving time but it's not significant and it will go down rapidly in the next few years all right there's a question here thanks for using uh the Q&amp;A form so what's the adoption look like from other i2s uh how do we help that's a that's a great question so we presented it at Ro call uh there's been some discussion on eth magicians which is kind of the go to place to discuss the proposal but we we haven't received too much feedback the only the main feedback we've received so far is that devs love it you know it kind of open UPS the design space to to depth that you would not think about normally so that's very good feedback but I'd love to hear feedback from other L2 teams other rups team teams if you can point out issues or uh anything that might break in the spec that we need to fix the earlier the better and then we can converge to a final spec all right so I just continue uh with the next section so we have uh these code examples basically three code examples of increasing complexity although not too complex setup if you want to either follow along uh well if you follow on you can just follow the the screen if you want to reference this later then you can uh take the code from GitHub uh it has all the solutions so if you don't want spoilers then don't open it yet or don't don't open the files yet all right so you can see the editor if you know the text is too small or anything then let me know and I can adjust so I want to walk you through a very simple kind of toy example just kind of to get a feel of how l1s load works from a developer perspective uh let me show you so for this example we will use Foundry uh many of you might have used You Know Remix heart head Foundry I think more and more people use Foundry uh that's what we're going to use here but you can use any of your developer tools that you're happy with uh we're just going to do some uh fast development and testing on Foundry and then RH will'll show you how you can also interact with a devet that we we're running so the simple toy example that I want to talk about is uh a counter so let's say we have this simple counter contract on i1 uh and it m maintains two entries in storage so one is a simple onside int and the other one is a mapping so uh nothing nothing fancy yet and then there's only one function it which is to increment this number and then to store something in the mapping I guess counter is a bit of a misnomer because there's also this mapping but uh you get the point we just want to have kind of some State on L1 that we can interact with so let's say you deploy this contract on L1 or someone has deployed it and you want to read from it how do you read from it from L2 so for that we will Define another contract called counter reader uh and the idea is that this is deployed on a different blockchain this is deployed on at2 so let's say counter is deployed on ethereum counter reader is deployed on on arbitrum or Z sync or any any rollup that adopts this uh proposal so when we instantiate this counter reader uh we definitely need to have the address so I I have that prefilled in here so we're going to store the address of the aan contract and then the question is how do we how do you actually read from thean contract so I'm going to show you first the lowlevel interface and then we also have some helper kind of utilities that make it much much easier to to do this so let just go back to the slides for a moment I had this slide previously so um this is a recipe of what you what you want to do uh you need to ABI encode using incode packed the arguments to this call static call and then decode the result so let's try to do this and and see if it happens so I'm just going to start by defining the payload and the payload is as I mentioned it's an address and we already have the address here stored that would be counter I could also call it L1 counter just to make it clear clear and then it can be one two or up to five story slots so let's keep things simple and just focus on the first variable for now now who who knows what is the story slot of uh of this variable yeah zero uh this is quite easy here but when the contract gets more complex then it also gets more complex like if you have inheritance Etc so one thing you can do is I usually use Forge inspect it's a kind of Handy command so you can use Forge inspect storage layout I believe this basically just gos into the solidity compiler and this will show the stor layout of your contract so we have number at slot zero and the mapping is at slot one uh as expected so I'm just going to go ahead and read slot zero and that's going to be our payload so we have the payload next step is to actually call the pre-compile so to call the pre-compile you need to have the address here in this helper I already have this hardcoded uh this is subject to change so uh as I mentioned the The Proposal is still not final and also there's an interesting discussion going on like what address should uh these L2 pre- compiles use should they con continue at the same address range that L1 pre- compiles have or should they have like a dedicated pre-compile address range I think everyone is leaning toward the second option but for now we're just going to use the same address that we have on our uh devnet that we are maintaining so we're just going to use this address and static call payload and what this returns if you're familiar with kind of lower level C inside evm is whether this C succeeded and the the result of the call all right so we halfway there um I'm going very slow because this is kind of an intro example I think for advanced developers this might be a bit boring but uh just hang on for for a moment so you got to make sure that this call succeed succeeded if it did not then of course we cannot continue uh now it depends on the final spec in the current imp ation there's no way that the l1s load fails once the transaction is included in a block that means that the sequencer managed to fetch the storage entries so it it should always succeed but U unless of course you for instance encoded the inputs incorrectly so you got to make sure that you do that right so it didn't succeed we just revert and if it did succeed then we can decode the data so the data very developer friendly again is just ABI encoded so you can use all the s uh tooling or or syntax to to decode it in our case for now this is going to be a single unide int so this is the number and I can get to the number by just AI decoding uh this return value all right so we we got to a point where we could read at least one of the story slots uh now let's try to test it and the test kind of also shows you first of all how you can develop with an load and also how this uh Toy example would work in practice so I have a Foundry test prepared here uh kind of the very convenient thing about Foundry is that you can use solidity for the whole development process you don't need to switch to another language uh to write your tests so in this case we do run these test in solidity but the problem is that envil and Foundry all this tooling is not aware of this l1s load pre- compile so to make development painless we created this uh this uh class that you can use or this contract test with1 load so this basically injects uh fake L1 Lo that behaves the same way as as the real one into your test environment so whatever you test with this should also work uh in the actual L2 context and then the test itself is very simple we just deploy the L1 contract um you can imagine that this happens on i1 uh for now we're testing it in a single evm environment so deploy the M1 contract and deploy the L2 contract with the address and then you try to read the contract originally we didn't initialize the storage Valu so all of them to should be zero then we call increment after this increment call uh when we read from L2 you should see that the state has been updated let's see if that works oops all right so far so good so we ran the test it passed and that means that actually when we called this read counter method what it did is it called l1s load l1s load fetched this storage from L1 and then it returned to the L2 context uh the only thing missing from this example is the how do we read uh the mapping because if I uncomment this line since we didn't implement this the test will fail as expected so so how do we do that um doesn't anyone know um so basically what we want to do is read the mapping value of this corresponding to this key of 1 two three how do I get the storage slots corresponding to this value I wonder if anyone knows hash of the message sender hash is correct exactly so some way you need to take the key you need to take the slot which is one in this case hash them AI in code and hash them together and that's how solidity calculat these mapping keys so it's a bit more complex but if you know what you're doing then not not super complex so let's try to add that I just move this to another variable oops it's actually quite hard to type standing here just hold on for a sec so you need to ABI encode I believe the first the first one is the key it's something that you kind of got to remember but RH will Enlighten you in a couple of seconds in the about the details so first is the storage casy second is the slot and then you just take the hash and let's let's see if that works maybe I remember it incorrectly in which case I can just just fix it all right so now instead of reading one slot I read two slots uh the call otherwise happens the same way I just need to add this additional argument here and also when I decode the results uh I need to decode it has two anide in so this will be first one is going to be let's say value zero and the second is value one and then just return this so it's not fundamentally different from just uh reading one value or two values okay let's see if that works so now the test should pass Yeah question cont oh yeah yeah so that's a good point I think the the feedback is this is kind of low level like who wants to deal with this we could if we could just you know call counter DOT number to read it this this would be more convenient and you can definitely do that I I think I want as is just a a building block and it's very easy to to build higher level abstractions on top of that actually let let me show you uh and then we can get to the next question so just wanted to show you this is how it works on a low level but we do provide some uh libraries a simple library in this uh repo if you open it so instead of what you can do is i1s load read read onite int and just provide the the address and the slots so I still I still need to define a slots but uh the rest of the code is basically replaced by this single liner so same thing actually just uh hidden in a library uh so as a developer it's probably much easier to interface with this and also we have utilities for onside in for bites for address Etc and also this is still not as high level as you suggested but using this is very easy to I can create a contract or generate a contract that looks just like this but is actually calling aod that question yeah that's a that's a really good question a question was can I specify which block I want to read from yeah so that that's a big challenge for sure so in the first iteration of the RP we designed the interface in a way that you can also pass a block number so you can read from arbitrary height uh that's for some applications that's a must have for many applications this is not needed and it also requires you to run an archive node because you need to be able to always serve archive data but basically one of the open questions for the rip like do we need this do developers need this if yes then then we can add this uh but in terms of reading stale data that's still a challenge because uh there's a delay between when the data is updated on L1 and when this information is related to L2 so this delay can be reduced but it's not instantaneous exactly yeah uh someone commented on eth magician exactly about this if you have any input for that discussion we'd love to hear or see your comment any other questions you let me check the Q&amp;A we can get back to the more general questions a bit later so that kind of wraps up the first example again a very simple toy example but kind of shows you the power of aan load and also shows you how you can use this uh in your application without too much added uh complexity now for the next two sections I want to hand it over to RH uh hopefully I think many of you might be dozing off you know my mellow voice and also digesting the lunch so R is full of energy and and he'll kind of shake you up [Applause] so Peter's Too Tall I have to just adjust this a little bit so hey everyone my name is Rh I am so happy that Peter went first because mine is going to be dialing it down a lot level lower u i mean to the extent that because it's a beginner Workshop we're going to be tailoring it for beginners who probably are not very familiar with Foundry as well but they also just want to get rapid prototyping accessibility by using remix so we're going to be using remix a lot shout out to the remix team and we're going to dive into the example first okay while it's loading up here I'm not too sure if I would be getting like bandwidth or if the demo gods are going to be with me so what I did over here was that I pre recorded this and we could go through this it's probably about 10 minutes and then I'm going to be narrating over it as well so 10 minutes this is going to be like super beginner friendly so for a lot of you I'm seeing intermediate to advanced level deps you're going to be bored out of your mind and if you're bored out of your mind hopefully I can sing you a l by and then put you to bed for a little while take a little nap and then be back up for a bit more of the complex types that we will be seeing uh so in this section in part to just a quick overview as well we have done three hackathons so far which uses l1s load so through those hackathons we have received like multiple feedback on implementation understanding how to rapidly use it in different hackathon environments so that you can quickly tap into it and start building the application that you're looking for so that is sort of where I will be leading this session most of for like the implementation side of things all righty so let's jump right into the remix Demo First this is going to be covering some setup in terms of like how do you want to set up your injector provider environment in metamask with the death net that Pier mentioned we're going to be going through that and you're all also in for some treat to watch me do a bit of debugging and watch my poor coding skills all on screen and just before we dive into it I want to give a quick shout out to Ahmed I see Ahmed there in the crowd he was the one who help us to also put this together so a lot of the credits go to him okay so without further Ado we're going to first jump into remix so this is me writing the L1 SL load demo. soul is this like how fast is this it seems like super fast uh let's do fast okay all right now I know that it's a little small because even I can't see it from here so I've enlarged this so in this L1 SL demo I'm going to do a quick demo on how you can rapidly create an layer one contract and a layer two contract just read L1 slow with less than 25 lines of code just to see how simple it can get so for this context over here we are creating an L1 contract so this would be on ethereum Main net and in this case since we're doing a prototyping version it's going to be on pooia we're going to be defining the first variable over here which is number of Type U in 256 and we're going to be putting up a Setter function so this Setter function over here is for us to override this number of variable and as we can see number is equals to underscore value and that's all that is required for the L1 contract again this is a very very simple example we're probably going to be speed running through this because Peter did a way cooler job with Foundry but this is also to cater to developers who are more accustomed to using remix so now moving on to the later to contract yeah fun fact about remix we can actually put layer one contract and Layer Two contract also in the same file I found that like pretty cool so the layer two cont contct itself like what P mentioned it could be an arbitrum or whatever type of rollup in the future that decides to adopt this piece of technology so very quickly I am already defining the L1 SL pre-compile address over here again I'll be sharing all of the resources on where we can find setting up for your defet it's all here so I'm just like typing it out l1s lo. scroll. systems if any of you are bought right now I'm just putting it up here also on the screen so you can also be very handy with checking out the resources that we have there's a specific section here devet and it has a table outlining every type of information you need in order to get set up with interacting with the defet and there you can see that is the l1s load pre-compile address and again over here right now we're going to be building the getter function for it and this getter function will be the one where we call the number from the L1 contract again this is me trying to be as verbos as I can but at some part not really I think I do a pretty bad job so you can come and provide me with constructive feedback later on and we're going to be creating two arguments over here we have the L1 contract address because we have to ultimately decide which is the contract address that we're reading into and we also have to define the storage slot number and over here since it's a geta function we're going to be returning a un 256 and oh yeah this is just me showcasing some remix functionality again we're diving into like what you can also do in remix here so moving on I've also written some comments on like what I'm about to do next probably should have done it in more like a twoo fashion but anyways we writing a call function to L1 contract we're not really defining the payload over here I'm just trying to see what we can do with less than 25 lines of code here so I try to be creative not really and over here we are destructuring already this lowlevel call and we're going to be uh packing the arguments which in this case it will be the L1 contract address together with the storage slot number and then eventually the destructuring of this process will return a bullion of like the success and also like the payload in this case I'm defining it as U data and very similar to Peter's example over here we will be defining like for Success if it's failing and it's going to be reverting with an error message over here okay I promise you we've wrapped up really really soon now we just have to convert the bytes we have to typ cast it from bytes to U in 256 over here so this would be the uh the syntax in order for us to uh to type cast it to you in 256 so over here very quickly just now you saw my wallet address and it's already uh set up to be with sepolia network so we're going to deploy this contract directly to sepolia and yeah this is me being a lot more verbos now we're deploying our one contract to sapoia so really really beginner friendly here where like tapping on to like the entire Spectrum term of even aspiring developers here okay so now we've deployed it oops and after we've deployed it it's probably a really good idea for us to also copy the contract address which I did not do but you can kind of see how the terminal from remix would help us to gather that information later later on so I'm setting the number here to seven just because we're at Defcon 7 ha found that that was a pretty cool thought process probably just myself so right now number is set to seven on on the layer one contract itself so now we're going to set up our custom Network for defet we're going to go through this process of how it can get set up over here on the top left you should be able to see like add a custom Network so over here you just populate the information of network name RPC URL everything you can just copy and paste it from defet it's all set up for our convenience there we go so this here I've already pre loaded the address for sepolia e now for developers who are interested in trying this out the foret the faet is here definitely recommend you to check out the faucet you get 0.1 subol e for defet and it allows you like Tinker with as much as you want so over here now that I've already added this custom Network we will then be able to directly deploy it onto defet so that's us switching to L2 con track and then we can directly deploy over here I'm going to be showcasing as well what were some of those errors that I've encountered so being very transparent as well notice that there is the transaction failure for not having enough gas I'll also just be showcasing to some who are newer to remix and also aspiring developers of flight what you can do in order to get this to go through so then we just have to bump up the gas so what I just did was I just bump up to one very uh I would say a simple way a smooth brain way of treating this by bumping it one then we are able to deploy the contract so right now we already have this contract on L2 so over here we're going to be passing on those uh those the argument that input to the argument over here we have the R1 contract address so in retrospect in hindsight I should have like copied the moment that the contract was deployed on toola but even if it's not you have a record of the past transactions in your terminal in remix over here pretty handy you can see that the contract address if this would go away is just directly uh tied to this contract address key here so you can just copy that and then you can just pass that over to your L1 contract address and storage slot number Peter has done a great job already everyone here is like gigabrain as well so you already know that this is like storage slot zero so I've also tried to be a bit more verbal so that people know that it's zero index for how evbm treats storage slot and you can see that we have successfully called seven as the number as a response so we're able to get that information from the L2 contract so there was also one thing that was lightly touched upon for the L1 s load technology itself so if let's say if it is in production if I'm not wrong it takes about 10 minutes in order for us to retrieve the information on L2 but if on defnet that's actually an artificial simulation so it's actually relatively quicker in order for us to get the information but over here here you can see that I'm trying to set a new number to Showcase that it actually takes some time before we're able to read that data due to us simulating uh the L2 uh the delay of the time that we're getting the information from the L1 storage slot itself so right now on L1 you can see that the number has been updated to 100 but when we're moving back to the L2 contract it's going to take a little bit of time in order for us to get the latest information so as a developer yourself when you're building in hackthon if you come into this part where hey why am I not getting this information it's like better documented inside the L1 sl. scroll. systems as to a bit of a delay for us when we are getting this information but I can assure you that I would say it's almost about 20 30 seconds ago or around there for the time of my testing this is me just site repeatedly pressing it in a way that I'm showing you that I'm actively interacting with the UI here and but eventually sometime about like 20 and 30 second you'll see that the u56 it will be updating itself to 100 so I think it should be now this is also me going through the different types of transaction that we see yes so it takes just a little while for it to update its information in order to get the information from the L1 contract address uh so just like in mind when you're also building using Like Remix if let's say you encounter this issue there's an L1 block inut delay time yeah it's better documented here feel free to also like check out the resource here so this is actually me going through a very Elementary way of what it's like interacting with the L1 SL load technology using remix so maybe I can pause here a little while to see if anyone has any questions but I think like period done greater job and then he's covered like all the possible questions so now what I think we can do is I want to touch on product refinement a little bit and what I mean by product refinement is in the previous hackathons we have different developers also trying to use different type of data types and different types of structures which are a lot more complex we're going to dive into it and see how you can immediately implement it inside your code in the upcoming hackathon or whatever hackathon that you're looking at or even if you're looking to just like build some cool right am I allowed to say that I hope so but anyways going into this hopefully this is not too small let me enlarge this okay so this is a pre-written contract in order to like facilitate this discussion what I've done over here is I also have a couple of contract addresses here and I'm just going to be using them and load them in directly into our L1 contract so over here we have the first one we have i1 contract okay so for this demo over here we will load this in directly into remix we're going to pass that contract address and this should be what you will see now again all of this information I want to highlight that it's already in the QR code that Peter shared we have all the information over here defon L1 Workshop if you head over to source and if you head into part two of the workshop you'll be able to get all of the code here directly so at the same time in a way you can actually be interacting with this as I am going through this demo with everyone over here so very quickly while we're just reading through this contract we can see that we are defining you in 256 there's a variable for it and then there's also L1 text is what I've call it for string and also by 32 which is for L1 bytes and some of them I have I have left the commment it's like storage slot at position zero storage slot at location one storage slot at location two but the subsequent one we're going to try to have a bit more of an interaction together with the crowd here and you guys let me know what you think of the storage slot for the subsequent ones we'll dive into them like later on so we'll be also looking into fixed array and also array with smaller data types for example like a u64 and then also with Dynamic arrays and then we're going to look at mapping Nest mapping and also struck so these are some of the data types and structures that we're using out there definitely there's a lot more complex on as well like what P mentioned there also inheritance but for the sake of time with respect to the time that we have now it's 250 okay we will be going through through this example that I have again it's a accumulation of the past hackathons that we try to refine the ideas upon and for this Constructor very quickly running through everyone for L1 fix array we have already instantiated a contract with several input already so you can see all of them inside here I want fix array goes with like in the array of 3 six and 9 fix array 2 1020 Z and 30 and so on and so forth and the following ones these are just set functions and then also geta functions for us to kind of play around if you're interested I know that in hackathons it can get pretty I would say stressful so you just want something quick and easy copy and paste and start testing things out so over here we're just going to take a look at what it is like when we are interacting with the contract already there are some parameters that I have already passed so I think the state it right now it should be reflecting what it is so for example when we're getting R number you can see that is it too small I hope this is not too small okay maybe this is better so u in 256 itself for the variable of L1 number it's already been instantiated with L with 100 over here so there are a couple more we're going to go through my favorite which is retrieve string retrieve string here this is interesting I love Devcon I am super excited to be here with all of you defon is going to be the best time of our life all right by but it's very interesting as well because for string type we're going to see how we can actually access the storage slot to concatenate all of the string because as we know it's only a u 256 for each of the storage slots but for what I have passed over here it's definitely way more than that it's not able to like store all of it so how do we actually concatenate everything and then actually retrieve the string that you want because there are some hackthon use cases that I've heard of developers wanting to also add maybe like a URL to create like different types of profiles and then like have it live on like L1 so this is why we have the example for retrieving string and how do we like concatenate all of it and if we don't what happens we're going to be going through some visual illustrations of that as well because the best way to show is by yeah visual representation and then for for the for stru what we have set in place is that we have let me quickly go through the stru over here we have the name and we have age and then some of some of the information that we have already put in place is like Alice is 20 years old is 21 Charlie's 22 and these are the three pairs that we have and then very quickly a quick run through as well if we retrieve bytes you can see that this bite is not all zeros you've got 1 2 3 and four five six for the sake of time I've already spent run some of this information I've already spit it in into this like contract address over here so which is why you can see that this information they are not just zero if let's say it's just instantiated you're going to just be seeing zeros and if let's say we retrieve like a dynamic array again we have instantiate over here you can see that it's 100 200 300 400 fix array 369 and also fix array 2 1020 0 and 30 so we can kind of see that I'm not lying this is my proof of work that I've done my homework everything here it is uh correlating to this address which has been instantiated okay so that is a high level starting point to get everyone accustomed to what this contract look like when we're trying to call it like using remix so now to the onward to the fun part the fun part would be to look at L2 contract how do we actually interact with L1 contract and for this example I have also deployed the contract already because I feel like demo gods are never always with me so I just try to prepare myself as best as possible to so everyone have a smooth brain experience just like me okay so for two of this contract here we have the basic L2 contract. so and this is going to be touching on more of I would say just three data types that we're looking at we're going to have a retrieve for L1 number which is the L1 number and then we also have the L1 string and then we also have the L1 bytes these are just the three data types that we're looking at so I would say this is probably the beginner version before we move into the more advanced type of manner of us calling the different more complex data types and data structures so for L2 contract what we're first going to do is we will first change our Network in for Network I have this as scroll l1s load and we will also just copy the address which has been deployed over here again we're just working remix over here so everything is whoops already set up okay so for retrieving L1 number so what we're going to do right now we are going to be reading through the contract together with everyone again there's like multiple ways of us actually setting this up we can even use the contract that we're planning to read and pass it on as an argument to the function itself but for the purposes of this demo in order to kind of like speedrun this as well what we have done is we initiating this instantiating this contract directly with the L1 abolute contract address in this case which was the L1 contract previously that we' have seen here so in this case when we call retrieve L1 number retrieve L1 number should return us 100 over here yes and so when we take could look at Peter's demo as representation uh basically I didn't exactly Define the payload as a line by itself that's the only difference but everything else Remains the Same right so a lot of the pattern this is me going through the same patterns running through in a recursive fashion so you can kind of see that actually utilizing this technology is not very difficult even for aspiring developers this is what I would like to try to instill to everyone here in the audience I'll say so we retrieving L1 number public view returns u in 256 over here the U the slot number over here I have defined it already in the local variable as zero because in the L1 contract again L1 number variable St uh Global variable is at location zero and in order for us to destructure this call here it's a very standard uh standard syntax I would say for us to destructure the information we get the payload which is data and then after that we typ cast it to you in 256 in order to get the result of 100 here which has been set in L1 contract now okay L1 string I'm going to touch on that a little later I have bites underneath here first so we're going to touch on bytes first very similar also again the only difference is that what we're returning right now is then byes memory and for the slot number you in for the L1 slot number here it's at location two I would say so this would be what we would be efficiently passing through to it and when we are calling we making this low level call we're essentially calling this address here this l1s load address is reading from here that we've defined in the global variable and we can create this low-level call and then we pack all the information the contract address and the slot number we concate both of it and code pack and then we make this call to effectively retrieve the dat data which is in the form of bytes and when we call it we can see that it is exactly reading to what was the L1 contract result like now for string type I find that string is quite an interesting piece of information I've heard some of the audiences are already very familiar with how to actually retrieving the information so I feel like there are a lot of like intermediate and advanced level deps here already in the audience so this is like fantastic also and what we're going to do is just kind of like rehash some of these Concepts that we have seene and for string over here I mentioned like test slots for example because there's a limit for us to store information in each of the storage slot it goes up like only uh uh you in 256 for example and so because of that there's like limitation for each of these storage slot what then happens is that we actually have to add subsequent we have to create a w Loop in order for us to concatenate all of the string information together and then return like what we have initially like pass at the start of it so for example right now string storage slot is located at location number one but if we were to pass on maybe the test slot of zero because it's always going to be indexed zero you can see that what it's returning is I love Devon I super but then it stops over there but if let's say we were to create a while loop for it so as long as while it's true we are able to concatenate all of the string data together together uh it should be able to help us concatenate the entire string result together and give us what we have passed like I love Devcon I'm super excited to be here with all of you so that was me like speed running it so let me dial it back and then we kind of see step by step of how we actually retrieve the L1 string so over here the L1 slot number is still at location number one the slot sequence here I've noted it as zero because it all starts at zero but init but eventually we're going to add the sequence sequencing to just keep adding it incrementally so that it can fully concatenate itself we're going to be defining string Ming string result as empty at the start of it and while it's true again we're going to be making a low-level call over here and this is where it gets a little bit more interesting we have the l1s load contract address but I've heard some from from the audience mentioning that we have to Hash it exactly that is correct we're going to Hash it and then we're going to typ cast it to you 256 and then we're going to add the slot sequence to it so whenever that is true we're going to incrementally increase the slot sequence because we know that there are still more information after that slot and what it looks like is because if us hashing this data subsequently if let's say it returns similar like 0x00 it will then break but before it breaks as long as it stays true it's just going to concatenate everything and return turn the string result so this is like a high level of how we can actually concatenate everything and retrieve the L1 string result here okay so again all of this information we have this code directly available inside the L2 contract here so for deaths out there who are excited to just get started with like tinkering with this here's one for all of you okay and then for the third piece third and final one I know I'm putting everyone to sleep right now we're going to try to make make it fun for the last one okay so for the last one over here we have the al2 contract Advanced type here and we're going to replace this with this contract all right so for this year it will be a lot more interesting because we'll say that this is a bit more complex uh with different ways of actually querying the information but very similar similarly as well we are still defining the L1 SL Lo pre-compile address up front over here already and the L1 slad contract address is because when we instantiating this contract it's directly using the L1 contract address and so that it stays as a global variable here we're also defining the L1 profile struct already which means that we kind of need to create the data type for what is an L1 profile struct take it in a way that we are creating profiles for our people this is a simulation and an example of this so over here if let's say say we were to retrieve fix L1 array we're going to be walking through the first information uh first I would say retrieve function step by step we're passing the variable storage slot in this case this variable storage slot will be referencing L1 contract where this storage slot location is and then afterwards similarly because it's an array the way to access it is that there is going to be subsequent location that it is stored in so what I've done is we just added in of course that's different ways of approaching it but I felt like it was a fun way to also get the audiences like engaged to see where people think the storage slots are but everyone so smart so I think they're going to get it so very quickly if I were to just kind of get the audience to think about where do we think is the L1 fix rate storage slot at this is storage slot three dang that's good all right three okay and maybe just a quick one we're going to plug this information in if we are going for retrieve fix array element here and we say that the storage slot is storage slot number three and then array slot would be I'll say zero because it's all zero index I mean call it you're going to get three because three was already instantiated in the contract here as position uh three as well storage slot three but what about for six and N where is the St storage slot for 6 and N four and five I hear four and five that's cool so let's give this a try we can go to the contract here and because what I've done is one way to think about it is it's just going to be added sequentially during the contract instantiation so when we are creating the contract already deploying it there's like three six and N so three itself would be occupying one storage slot six would be occupying another and nine would be occupying the subsequent one so what I've done here is that when three + one is essentially storage slot number four and you're going to be retrieving six as uh the return result over here and the way to access this information you're going to start seeing very repetitive type of syntax it's also encode uh using ABI in code pack where we access the L1 contract address which is from L1 contract and in this case it's just a variable storage slot plus aray slot again we can always argue that we don't need array slot the reason I've added that in here is just to show what it's what we're really thinking about we just like adding the array slot based off of the length of the array but in this case actually for variable storage slot we could have just mentioned that this is variable storage slot of four but the array slot let's just say if it's zero we should still just be getting six because technically this is storage slot of four yes so we still be getting six subsequently if we look at Dynamic array Dynamic array gets a little bit more interesting because during contract instantiation time it's more of the length of the array that gets recorded uh into the storage plot itself but the data itself is stored somewhere else which we will need to access it differently so if we look at this lowle call over here it's actually ABI and cack and then we have the i1 SL contract address and then we are hashing this variable storage slot and then we are actually adding subsequent array index on top of it in order to for us to get this to retrieve the dynamic array number so if we were to look at an example over here for if we look at L1 contract so we jumped into like Dynamic array over here yes we jumped over to Dynamic array very quickly what do people think is the L1 fix array to storage slot six is it six 7 8 and N though why is it not 6 S 8 and 9 sorry it comes up to you in 256 yes that's correct so actually this occupies at one storage slot by itself so just storage slot six again I feel like the reference from the visual representation visual illustration from Peter using like Foundry to check out this storage slot that is like really helpful to also look at it but this is also us going through the example through the lenses Like Remix and see what we can actually identify so the storage slot here for L1 Dynamic array it is actually yes storage slot s then so for us to access the storage slot s over here it's going to we're going to pass seven as the input and then for array index here it's going to be zero and then when we call it we're going to be getting 100 and 100 matches with what we've instantiated also as 100 over here but the way that it is uh the way for us to actually sequentially call the variable the in the the information of in this case the U 256 information we're going to be adding incrementally plus one because that's how the information is packed in the storage slot so it gets hashed and then it gets type cast UN in 256 every subsequent number that gets pushed onto that array it will be occupying that uh slot respectively for the value so even though when we push new information on top of dynamic array that is we just have to add a subsequent new uh increment plus one to AR index and we're able to access that information and fetch it when it comes to decoding this data it's really I would say um the same type of syntax that we see for retrieve L1 number it's AI de code data and U in 256 moving on to the next one I think mapping is a interesting one but because this example here L1 address to mapping this is fairly straightforward we have the L1 address to number mapping which Maps this contract which was instantiated already the same address would then give you a value of 100 so uh with respect to time I think I only have 20 minutes left what I will do is everyone will be able to like reference this information over here I will skip through retrieve L1 address to mapping but instead we're going to go through a cooler example which I think has seen a lot of use and a lot more uh interest which is when we're trying to retrieve and resolve ens handle there was some feedback mentioning that there were there are lot of um nested mapping use inside of ens contract some of the feedback that we've also gotten was that it was relatively over-engineered I I'm not too sure but to some extent we would use L1 s load gives you the capability to access and resolve your interet handle at L1 at the layer one itself right so for this function when we call the retrieve L1 nested mapping this will be a bit more interesting in the sense that we have mapping address as a variable and also mapping string and where do both of these uh arguments come from is that if we look at nested mapping here where do we go so for L1 nested mapping it's essentially like an address that maps to another mapping of string to then finally resolve it to a u in 256 so for us to act to resolve to the final you 256 result there like multiple ways that we have to first hash the slot in order for us to access that information so because there is two levels of mapping over here I would say so we're going to have to first first hash the initial slot and in this case would be like K 256 and then similar syntax e and code pack we have our U 256 here with the mapping address mapping address this will be the address that maps to this new mapping of string to U 256 and we're going to have to like pass on the variable storage slot now do note that in this context over here you notice that this method of concatenation is that the variable storage slot comes later after the mapping address so the way of hashing it the way of accessing mapping is that we first structure the input I would say to the left and then the variable storage slot like to the right over here and then as you have multiple levels of mapping you would add on uh additional levels here so for example like buy stud through initial slot and then maybe buy stud through like second initial slot and so on and so forth and then once we have the final slot over here we're just passing the final slot information into our lowlevel call and then since it's a u 256 we're then able to like decode this information directly so let's give this a try over here for L1 contract we have initiated it with this address ABC and also 1,000 and it should be returning a value of 1,000 so this L1 contract it is over here and we have retrieve L1 nested mapping here we will pass on address here first and again for L1 contract this is storage slot seven so we'll pass on seven here and for string what's for string ABC let's do ABC ah but when we call with ABC we're getting a value of zero does anyone know why okay I'm getting everyone to like those off so let me answer the question because we're going to have to follow exactly more like a check something I would say where we have to follow exactly what was being passed in this case it's supposed to be like ABC uh let's see then we have this call then we should be able to retrieve this information let's see contract address oops that is not storage slot of seven because for nested mapping it goes to 9 let weall it there we go the value comes up to 1,000 so for those of you who are interested in understanding how to access nested mapping this is a good example for for you to start diving deep into for the last example I know I only have like 17 minutes left I'm going to like speedrun this so for the final function here for retrieving stru this is actually the same one we have seen the same syntax like previously and this actually goes back to mapping so when we look at how the mapping for here we go going through here so for mapping no not mapping my bad this is with array index it's very similar because the way that it is yeah so for like Dynamic array number the way that Dynamic array stores its value the way that it accesses the storage slots Dynamic array they're very similar to stru actually exactly the same so for example I'm going to Showcase a quick example over here for retrieving stru the variable stor slot we're going to look into this again we have seven here and then for address to number we're going to say eight and then here we're going to say nine but for L1 profile strun do we think that this also occupies a storage slot no the answer is no so I'll say no and then over here it's actually storage slot of 10 and finally over here if we were to showcase the example of this whoop so for retrieving struct here it's going to be variable storage slot of 10 and if we pass in zero as the array index we'll be able to get this value in bytes but this is so interesting because the payload that we've Define it comes out in bytes so this could be like a homework for everyone to kind of like test it out because this contract is already written you can see that how you can access this information but I've also created some utils over here for us to convert for example like bytes to string so if I pass the bytes value that we' passing you can see that it returns like at in this case so these are basically just like a set of contracts already written in solidity for us to see what it is like implementing and trying to extract information from L1 using uh two different types of data types and two different types of data structure so yeah this is all I have does anyone have any questions or do we want to like go through everything first then take questions later yeah yes using the gas cost I remember reading that there were some but maybe I'm going to like get Peter to also like but for like a general call usually there's no gas CA yeah but I do remember there was also a topic on this but I will lean on to like Peter to also like talk a little bit about this that's a good question thank you oh yes you have yes come again yes is it okay yes yeah so we can probably spend the rest of the time on questions uh there are some interesting questions in the in the form two so I I believe your question maybe there were two questions but the second one was why do we need to have all this MPT verification yeah so you as the L1 if you run an L1 validator you know exactly the state but you as the L2 node or USD L2 contract you don't so what that means is the sequencer returns some value to you to the contract color but the sequencer could just make up a value we don't want to allow that so that's why the sequencer as part of the verification could be fraud proof could be ZK proof it must provide the valid proof saying that hey I I gave you this value and this is the actual value stored in our one uh it's much stronger than an oracle I guess so I would say the sequencer optimistically relays this information at this point you can view this as an oracle but you also verify it eventually so uh there's like a period where you kind of trust the sequencer and then eventually you verify it so the sequence of longterm cannot cheat so if you have two contracts let's say on the same blockchain on L2 uh if one of the contracts exposes the storage say a view method then you can read it if it doesn't then you cannot so usually you would need to call RPC uh so that that would be another interesting proposal just let letting you to read arbitrary slots from other contracts maybe that's a bit too invasive uh it's useful for as a building block between L1 and L2 I believe but for L2 to L2 applications or L1 to L1 applications I'm not sure if this is super useful um yeah the proof of inclusion is just a verification so that's kind of the Second Step I think there's a related question before we we go to other questions someone asked Can can I utilize L1 to call a view function on a contract that's an excellent question because there was other proposal that's called L1 call which is exactly about that so you would call this also pre-compile uh from L2 contract but instead of this very lowlevel access to storage you would trigger a view function which is much more powerful and safe in a way the problem with that is that it's much easier to verify it so for instance scroll we have the type 2 zkv ZK evm currently we have our own prover and it works for scroll but for L1 call you would need to spin up like a whole different execution environment with type one Z KVM and and create a proof for that single call and aggregate that proof together with your original proof it's not impossible but I don't think it's practical at this point so and kind of feels the gap of of giving you something useful and practical uh but it's not as convenient as as a as a call um I think we we had a question somewhere there if not yeah go ahead yeah so that's one of the prerequisites that I said is that the L2 should have a notion of the latest L1 block and the way we would implement it is that the sequencer of scroll relays blocks from i1 now how recent these blocks are is kind of a security parameter of the system if you wait for finalization that's the safest but then you have to wait there's like a delay of relaying information of like 10 to 15 minutes if the sequencer is waiting for a couple of informations then there must be a mechanism in the in the rollup that reworks if L1 reworks so1 right so the the sequencer relays the album block hashes to L2 so basically you could also read directly the L2 State root or the L2 L1 block hash sorry L1 State tro and L1 block hash from L2 State and that's what kind l1s slot gets access to but it's a very valid question actually uh that's one of the open questions like the sequencer could just stop relaying this information uh currently there's no mechanism to force the hands of the sequencer to keep relaying information so it's possible that you read stale information uh we need to do additional work to support applications where this could break break them but in most cases you could assume that the data that you read is maybe 5 10 15 minutes ago from ethereum uh another question no worries uh just a few I think we're about to wrap up I don't want to take any time from the next section just uh you mean the road map like moving on or yeah so we we do have an implementation and that's what I linked before so we do have this devnet but it's not production ready yet so that's why it's only a devnet it's not part of our test net and Main net uh there's still a few rough edges that we need to figure out and also we don't want to deploy it on not until at least two rollups adopt it like this is only really useful if if multiple at2s support it and to to say say why I just want to mention that we have a third example that we didn't uh get to today if you open the repo then you can see it and it's a key store the idea of of the key story is that you you you know we live in a multi-chain world so you might have your wallet your a wallet some whatever you prefer on multiple chains uh and you know it's usually a multi so you can can have uh multiple assigners multiple Keys associated with it now in this multi chamber this becomes very um inconvenient to maintain if you want to add the key or remove a key you need to do this again and again for all of the chains and it can be you know five 10 different chains so the idea of the key story is that let's say you have a key store contract on L1 and it the whole purpose is to to manage case you can add and remove case and all your wallets that are deployed on again optimism scroll arbitrum they read which are the authorized key from i1 and they just use this so you can update it in one place and it automatically updates with some delay on all these other chains so um that's kind of to show an example why it's only useful if it's multiple rollups that's supporting it because these use cases are really unlocked by this feature yes so each each of the rollups will need to implement it and because rollups work differently there might be so the specification and the inter interface would be the same but the details of how it works might be different from rollup to rollup so that's kind of an implementation detail that's that's left to the rollup team um apologies there's a bunch of questions that we didn't have time to answer uh if any of you are interested either devs or protocol maintainers who are interested in adopting this I'd love to chat with you so find me anytime after this session or or later and we also have another session on Thursday 5:50 p.m. about the same topic uh that's all for today thank you [Applause]
