Cross Chain Comms
Inside Aztec Labs · 23 Aug 2023 · 51:05
Aztec team lead Lasse Herskind presents the design of portal contracts that let applications interact between Ethereum L1 and the Aztec L2. He covers the rollup contract, message boxes, intrablock ordering, the pull-only message model, error handling and designated callers, with a Uniswap example. The talk is part of the Inside Aztec Labs series.
Speakers
Topics
From Inside Aztec Labs, hosted by Aztec Network.
Transcript
portals L1 function calls and that's essentially what we'll be taking a look at now and a little on some contract stuff uh so it's essentially starting out with some of the contract stuff and so from Milestone one the roller contract is super super simple and as Mike also alluded to it just says you have one job make sure that this like State hash is on track then that you only have updated when there's a value proof so I sent you to have this can you can you guys see my mouse yeah okay so you have this transition function that since you're taking some State and a block and then you're
getting this news date and the thing that the circuits and this roll up Contracting compilation is doing is enforcing this T function um mostly the circuits but essentially as a point before a sequence of being throwing this large blob of data and the proof to the roll up and roll Within decode this into some more meaningful data that we can pass into a to the circuits and yeah then we will use like this this contract verifier to check that the uh the data we got from the the block together with our current
state gives us this like new state and if the if the current state is not aligned or proof is invalid the entire thing reverton nothing essentially happened um so this is what it looks like at the moment logically and just to show how simple it looked from the contract point of view here it's essentially just like one function to execute a execute the verification verifier and then some decoding for the the first Milestone we only handle the transactions like inside roll up or the first couple of milestones um so we don't need like anything to go
across this really and nothing not much going on it's contract at all it also means that we can pretty easily just make the contract fully immutable and also in the future it will not like the roll up itself will never hold fonts you will have these portals that instead are holding fonts which means that 90 of the code from as they connect is just removed and we have this one function left really and sorry and on the naming I I will update it um so with that in mind we can figure out like what is the these portals and what do we actually use them for
so like a port is really a way to make this uh cross chain application so in this case it's like say die is an application and you want to have you want to have both die on like L1 and L2 then this application is a way to to communicate between the two um two layers and because we want to say it this is like the same thing on both layers so when you are in layer 1 or in the layer 2 only you are pretty free to communicate between different contracts um but when you want to move between these layers we are limiting it to saying hey there's
like one pair so one L2 contract and one and one contract or L1 address really that are like linked hard together and practically you could have a it doesn't need to be a little one contract it could be an eoa um but that's a little weird in most cases that will probably be a contract and some of the questions that are often coming up when we like have mentioned this hard link is really like why are we going with this link between this one to one link eoa is an externally owned account so that's like a user uh so you could have that
on the L1 side it's essentially like a meta mask that can mint fonts inside the Aztec with your special um with your special USC or whatever yeah I hope that answered the question there hey if someone can like raise their hands when that's the question otherwise I might not notice it um bro take a look here and there um so we're taking a look at why do we have this link and it's a there's a bit of racing on going to there so really we are taking a look at like how do you order stuff inside blocks one-on-one
um so some of this was alluded to in Mike's talk as well so really when we are in the all public world so in the wood of ethereum uh when you want to send a transaction you essentially saying it hi blog producer please execute this intent that I have specified in my public transaction and you then have a bunch of these like intense ordered one after each other and they can all do the same storage and seriously have if transaction one is ordering a balance in this token a then when we are reaching transaction free and it reads it's reading from this new new value so everyone is is um like acting on this the current Head
of the State um and you this works fine when you have one guy executes the entire thing it gets a little weird when we have our private world where you are essentially executing these things locally then proving that you did it correctly and then what you're passing on to the sequence is essentially hey I did something here is some outcomes from what I did please handle that um so you're getting into this case where because you proved it at some point in time you can only have taken into account the state at that point in time so everything that you're reading is
um in the past but when you're writing you're essentially giving all of these uh like nullifiers and new commitments that you want to roll up to insert um this means that transaction free here can really depend on what happened in transaction one when they are both doing this private stuff so I can't like read directly from your I think because I didn't knew about it yet um which gives us some like weird um gimmicks when we want to do some of this ordering um essentially it gives us this case where
because we have everything is happening in the past with our storage you can't really put and so normally in arbitrol whatever you have in your storage set a value like this is the address that I will be receiving stuff from if you're putting that into storage here you could have updated and updated it and I will then make a proof where I use the old ownership and in the enforce this transaction that's not really a good thing so we can use Public Storage really at all in fact everything executing inside ethic because of this weird flow with
everything private happening in the past you execute private functions and then you can go with public and you can't really just jump back so you can't have these like Access Control in public storage which gives us a case that should be put in private storage and tell everyone about it um would just end up in a case where I ended up with every application having different ways to um to enforce this so the easiest solution from R1 was essentially okay we just enforced one to one and then uh devs don't need to enforce this thing
um if a Dev one there to be like more input from Melbourne they can handle it in a L1 contract instead so moving on from that I hope it was not too confusing maybe a little weird um moving on from what the portals were we need to figure out what is actually a message like messages the stuff that we would pass in between the layers that we need to know what it is a message is pretty simple it's like some sender and a recipient and then some some message here it's like a message hash in practice we could also have linked it to just be like a specific message a short message the nice thing with just
taking the hash is that we don't need to enforce a lot on how long can these messages be uh we can certainly essentially put it up on the developers to say hey I don't care what you're sending across as long as I own like the bridge only needs to handle these um small small messages then you can unpack it from a hash yourself um when we're dealing with L1 actors we're here inserting like a chain ID the main reason there was as we alluded to earlier and it might start actually that if there's multiple changes I can all those do stuff inside the Aztec if you
just have an address as the portal um you could have address collisions um essentially where someone on polygon could use like could own your portal now or could set messages as if he were the portal so we need the chain idea the reason behind not needing a chain ID on the L2 actor is that all of our message passing is handled through a contract or on A1 and we can just enforce that only one roll up can read messages from there so there's not possibilities to send invisible places okay um so we know both the messages we know
what the portal is then we need to figure out how to send how to send these messages between portal and something on L2 so essentially we're doing some using something we are calling a message box um so we have some sender he can insert a message into this pending messages at some point in time the roller will essentially move messages from this pending box into the ready box um so this happens atomically it just means that hey he can't just remove it from one side and not insert in into the ready he needs to do both and this is needs to be enforced by a mix of the contract and the uh the
circuit and then after this this move the recipient can consume this message and consuming here meaning that you like spend uh spend his commitment um so this is like one directional and you need one in the other direction as well to handle communication for back and forth we have some specific changes that it's not as simple as just having two mainly that our L1 like L1 and L2 don't really support the same functions as easily
um so we end up in something that looks closer to this we're on L2 we're using append only trace and nullifier set and on L1 we're using a multi set just means that hey you can insert the same message multiple times and we need to like support this just to handle a case where AI deposit five if and tomorrow I deposit five years again we want to that to be possible um then we have something that's also little maybe art when because everything that's going on inside L2 only really happens in a transaction in a little one so when
the Roll Up is executed it we don't like practically need to have this pending messages from l2121 we can just insert them directly in this like ready messages on L1 and so just skips that that one step um but overall the flow here should be fairly seems to figure out um any questions related to this before we move a little dude it doesn't seem so um we have some issues though and it's really fees and sequences here and this is not only the fees for
executing stuff in L2 we have some issues with the communication here so you can have a case where the portal is a die token deposit so you perform this deposit into the portal with your funds are now logged in the portal it's adds a message into this pending messages box but in doing so it underpaid um in in fees so the message is never moved to L2 um this gives a weird case where now the fonts are just locked and so you need some way
to handle this funds um or like either bump the fee cancel the um depending pending messages and kind of needed the portal layer to also handle that as well which is a little tricky um then we have something that's also a little weird that we were doing we're doing like pulling so um normally you're having a case like this for anything that happens across chain where you have a user they move to this like message box what we're calling
message but really uh they perform a call there and that is the performance call to the contract so if we look at the code here we they have some checks don't really matter for us and they're doing this target call with the message this is fine when you're doing public to public stuff it gets a little weird later on so essentially we yeah initiate a message to roll up moves the message and then to execute it we have this full call data in the message which in our case where the correlated could be related to private inputs is
just not something we can do and so we need to pull instead which is giving us a flow like this where the user would go to a contract give it it has like some inputs the inputs does don't really matter that much in this case actually as long as we can compute what message we need to consume from those inputs um and then the contract will go to this like message box consumed the message this means that we could have a lot of private private inputs maybe a secret somewhere in there and then we're just taking the uh Cody I can see you raised a hand yeah sorry I I had to step away for
about a minute uh maybe I missed this but what like what are some concrete examples of messages and so it let's say that I I deposit die you want to move die from L1 into L2 it's a message here could be the amount that you're deposit in a and a hash of a secret that like if you know the secret you can claim these fonts on the other side okay like with a transaction they like the message is the same as like a description of a transaction of some kind it doesn't need to be a description of the transaction it's it
could be like a subset of data that's used in the transaction um okay say it just uh thanks okay um so we can take this this example actually with the die so if you're just doing a plane deposit uh you could specify okay I'm depositing like 500 die or this is actually a withdrawal but we could do the same thing the other direction and then when we're doing it into the roll up we'll probably not specify who should be to we would specify a hash of some secret that hey if you know the secret you can get these
fonts uh it's not transactions for the polls it's but it yeah there's information that the polls can use so in the most part we have something I have an example later that consumes of it but it's it's not a regular transaction you can have a portal that also consumes some multiple messages um is essentially just a way to communicate between L1 and L2 and you could put really whatever you want in there uh the reason it's not a transaction is just that you're not specifying all the code data so you you could see this part of the transaction yeah it's like the it's like the almost the authorization for transaction is the
way I kind of think about it if you look at the roll-up in Aztec connect example um what what you would do to kind of model this in in this flow is like all of the aggregate D5 deposits to say um uh Lido would be kind of messages on on the kind of messaging queue um and they will be for one particular contract that contract could incentivize someone to come along on L1 um consume all those messages invest the funds into uh Lido um and kind of then put messages back on the um on the inbox to kind of update balances uh back on Aztec so it's kind of like the ingredients for a transaction but the uh it's not actually doing the execution
um that will be done by someone else because I was kind of Imagining the different like individual users would possibly be passing messages to each other is that a use case or no that's not the word messages like you could do it but it seems like a very expensive way to do it yeah right you made that for about like that's something I could think of it's like your mess your vote could be a message uh yeah you could essentially if you want to do it like a boat you could just consume all of them yeah in one way they don't really do anything on the other like on the other one they just like
communicated across uh Joss uh so I just want to clarify my understanding somebody on RL to invokes an action which they want to see have an effect on L1 what will happen is the pre-image to the action they want to perform goes into what some public store not the action that was the thing is some like subset maybe after action you don't want the entire action as then you're getting into this yeah pushing case which we have issues with if we're doing anything private um but you have part of it made by just
let me just skip a little ahead and I'll have an example that shows it a bit easier um so this is what happens for like the eye deposit um essentially have it it's the same thing if you're doing the other direction um so you have a user that's like invoking this deposit function have on die portal the dipole will pull some fronts from his account and then it will send like a message to uh it also message here if it was inbox and outbox there was reload this one um oh um I don't know maybe let me see how to assume this thing
okay assuming zoomed out um one sec is this okay um so this message is sent along the message here could just be the amount and then the secret that someone like the the hash of the secret someone needs to to know to to consume it a roller but then executed this message is inserted into build two side of things and you can perform this like consumption of the message which would be that you go to the ill to die contract
and it consumes this message and you now have five dial whatever you deposit it and the same thing if you're going to the other direction did that help a little or still weird oh sorry go now you go ahead um is this separation like this pulling because it would create a link between the Layer Two address and the layer one others that is contributed or wise no so say you're pulling say you push a message and you if you're pushing a
message you would have essentially let Target and the call data the stuff that is in the cold data could be private information you can kind of avoid it here to say that you're doing a push where you're doing the deposit deposit is 500 die to a bottle um this is not what you really maybe want to put on here you you would want just hey 500 die deposited to someone um and you can't do that directly if you're doing the push as it would need
some of the information like in this call later um but what you're doing with the pool is that you you have the 500 and then you have say hash of your secret then when what you do when you're getting to like deal two side of things so when you are over here is that you say hey this is the account that I want to have the funds on here's the pre-image of that secret and here's the amount all of these could be private inputs so private function and from this you could compute what is the message that should be consumed so you have the amount and okay you has the pre-image those two together okay you know what
message to consume so now you can save the message so now it's no longer public who received the funds on L2 which you would have if you're doing the yeah the pushing yeah I got it thank you um but it's it's an it's a little annoying as it makes our flow different from everyone else um yeah is there more related to the savior yeah would that create a friction in terms of user experience like would the user have to also initiate a like collect transaction on L2 in order to
actually collect that die that ESD positive yeah but that's essentially the same thing you're doing now on connect so on Optimus Mendoza because you're pushing it in you can forward some gas and you have all of the information to execute it so that's fine to do we can't really forward the gas as we don't have the entire thing I get makes sense yeah imagine it has to connect transaction you deposit a one and you send a transaction to L2 you can do the same things in parallel um they may settle two different times um uh but that's okay it's also possible to imagine service
providers that like could abstract this away and if you're like oh I'm fine with one app essentially knowing the app will know that I like deposit and die but they can just like do that pull on my behalf and then just send die to my account so at the protocol level right that's right yeah yeah it's a protocol level you're saying hey since they're saying someone needs to execute this but that someone could be not you so you could set it up essentially saying hey I generate everything that someone needs and then I put like some server please broadcast this when um this thing has been been included um
yeah so the pre-images to these message hashes how are they shared are they going to go in call data or do we need some other component for data availability all of the data is essentially which direction uh I guess uh l2201 yeah L2 to L1 this is some of the weirdness it's probably not going directly into um like one call data but communicate it over just the peer-to-peer Network simply to make it cheaper most of you would have that it's the same guy
initiating it that wanted to execute it so you don't need to like necessarily pay extra so to share it with the entire world makes sense yep okay um we have because the design is a bit different we need to have like some standard that helps a bit along some of the these issues like error handling um this is actually pretty similar so if you were doing autism is an upstrom uh because everything is happening async when you're doing a cross chain you have no clue if it's actually succeed or not when you're initiating it and you also have this issue with the
yeah just mentioned earlier if you underpay so it's like hanging these messages never executed and we essentially need to have portal devs handle these failure cases so say you want to do a swap on unit swap but the everything is like going through as it should but the price has just changed too much for your transaction to execute at the point in time where you're actually trying to execute it um and let's say that the price just never goes down again you want some way to be able to like okay this thing is not executing as it's supposed to send something back to L2 that there was a failure please unlock my like the
funds that was locked in this transaction otherwise you end up with people just having locked the funds forever which is not not ideal um a separate issue is if right just called designated Cola if we want to support having like bundles of transactions or these messages going on across chains so say the unit swap is a case of this you don't just want to like you need to send some fonts from O2 make this swap get some funds back until two so you're doing three different calls really um you need some way to handle the ordering if you if there's no ordering
enforced by this you could just like try to do the Unison of course okay no fonts then try to withdraw afterwards so now you're sitting in a case where okay nothing really happened as I wanted it to but something was executed but it's it's not the best case we want or the case we want so we need to be able to have a case where we're saying I want to have only a be able to stop the consumption of some message and if you could do that you can have these um uni swap like transactions where you enforce ordering through saying who who should be able to call what
essentially getting this case which is a super tiny to look at here and but what's going on is essentially saying that the uni swap portal contract is the one that needs to be initiating the die withdrawal and do a deposit of of if so here I'm swapping die to if so that's like free interactions on both sides of the the chasm um you're having the initial withdrawal they swap and swap happening on build two this kicks off all of these messages 201 and then you're executing
starting with the the unit swap portal the unit swap um Paul will start by okay withdraw some die because we need something to actually perform this trade after that have received the die performed the trade after that make the deposit of wrap these into the roller to get the like the result back and then at some point you can do this like rep if the deposit in the end it's pretty annoying to deal with more complex stuff which is probably also the reason that no one is really doing this uh across any of the other uh cross chain stuff like people mainly
move tokens or call one function they sell them to these small more complex things um well we kind of want to support them but we can't support it directly at the protocol layer by doing this enforcement so it needs to be something that it becomes a standard on there the portal Developers and then I just had a small description of drawing of the roller contract when we're moving beyond Milestone one uh just inserting some of these these message boxes um I came there um essentially we'll be setting up this registry
that is a contract that points to Delta contracts um and this is also what allows us to do an upgrade in the future if you have this upgraded mechanism you can essentially just redefine like this contract is the new roll up but it needs to be able to still consume the messages that were pending beforehand so we need to be able to just swap the roll up and we do that through display registry um that's the main thing I have related to everything that's really merges passing I released a cross chains something like this cut it here
uh yes some questions oh on the um kind of multi-step L1 low um like you you basically have a contract on L2 that you send some uh die on l22 that you want to be spent on L1 um can you just run through again I understand the ordering is important but does that mean that in the messages that you will be constructing like the you specify like a cola so say the message is uh 500 die withdrawn to the uniswap portal and this message needs to be like consumed by the Unison
so the units were called portal needs to be the one that's that calls the dipole to start this message and by doing that you're making sure that hey I can't just execute your thing for getting 500 die into the unit swap portal and then perform some other action um how does an L1 contract tell another L1 contract to consume a message it's like a defined interface is that what you mean by status essentially you don't need to tell another it's essentially that you're telling it directly by having on the Die Portal a withdrawal function that is by taking some inputs so you could use your the message sender as like where should the funds go whatever
and it's essentially taking a two and an amount and then it's checking that the message is coming from like this specified the designated Cola but here the the two would be the unit swap model the amount will be your 500 I and a designated caller would be the unit swap portal as well but as because this call is made from the unit swap portal okay this is all fine it consumes like this message and sent the 500 die and then it performs this like the swap afterwards and if the swaps fail the entire thing is reverted so the the message was never consumed in that case so it constructs the the message out of
the arguments passed into it yeah and then consumes okay yeah it gives us a nice way to have stuff that's very close to like exiting a normal D5 position when you're actually exiting the roller okay yeah lastly have you thought about how like an nft integration would look through the portal contracts like with openc potentially um so just like depositing an nfts are regularly or if you're thinking about like buying it and nft directly from the roller bride yeah doing essentially all the things
where like you can buy nfts anonymously you could do some listing of nfts through L1 um it's pretty close actually to this Die case so say that you have instead of die you have generic nft uh one whereas this like portal contracted up so you have that they also assist on L2 you kind of need them to exist on both places to uh make it work well um so you can then have a transaction from L2 that is doing first a die or feel mostly by nfts with if directly
right so you would have a withdrawal from from the roll up in if to this like um open C sales or buy um portal and then you have a call that is to directly to this openc uh portal for where you're passing it like okay I want to buy this n of T this was the price and probably uh who should receive it on the filter when you're sending it back so again this idea with hey I'm sending this hash of of some secret alarm and then you have a flow that's very
close to this thing when everything that's saying die that would be with and stuff that was wrapped either here would be nft instead and so the flow is similar in these two cases and then some of the nicer things compared to as the connect is that you're not limited to like 64 bits of custom data you could pass in a lot so you could have the Dubai like 10 different entities and get them all deposited um and for some of these nft collections or I know open c will have or what is it artworks some of these have multiple collections it's actually on the same
contract address but you could also have one portal that is for a lot of different nft contracts and then you're just saying hey this is the nft portal so it you don't have to deal with 10 different contracts for having these these 10 10 of these just deal with this one okay awesome yeah so did you make that that part a lot easier yeah it's still yeah it's still annoying when you have to go through a lot of these things but it's not like the end of the world uh just set it up so I would get someone civil experience you will probably end
up having a separate Market over on del2 as well but if you're doing like very large deposits into something on one this could be is something that's meaningful or simply to control a multi-stick on L1 and something like that from L2 you could essentially have your entire position sitting on L1 and just have the access control from it too and then you have the whatever saves normally doing with hey you can only move 10 of your balance whatever so you're just using the L2 as normal like um normal management and then if hits the fan you you can go to L1
directly we will not support aggregation batching directly someone could do it um but it's not like natively part of this thing um but yeah you could you could end up with sequence as that essentially do some of that themselves or just like applications that you can simply have CK money as an application that don't run a sequence at all they just collect a lot and then they build one of these large like messages or messages with a lot of fonts
yeah I do some thinking on this as well like there's networks like um gelato or um chain link have Keepers um so you could set up a um portal contract that has a keeper function on it effectively keeper is just there's a function you can call where you get paid a certain amount of fees to perform like a piece of work so that work could be check the message queue see if the batch is ready um if if a batch is ready far off the batch for a given um uh kind of defo protocol so be quite easy to build batching functionality but using other people and what other other systems which send the actual transaction so it would be the case that in the
message box there would be like multiple individual messages which would kind of like represent the same action and then we would have like this you would essentially have before that step that you say you have storage on like your mid stuff right as events just on L2 or as data I don't know to where you're collecting hey these 10 guys want it all into the same thing then when you're collected Arnold 2 you can set one message to a one really so similar to how good is doing on L1 you just have that the coordination part is happening on also you could don't know L1 as well though right it would just be more expensive
yeah it's just expensive but you're basically trusting the logic of the physical contract so the portal contract would have to say wait till I have 15 messages when I have 15 messages um I will exclude the function um yeah it's just when you add that step you could just as well do it from there to a logic and then only if I win good ready Adam you had a yeah yeah I was just wondering if um yeah generally we're assuming that the common L1 protocols we get L2 wrappers or are we expecting the user experience to be good enough just calling L1 directly or like is there or do we expect like I guess yeah so there's a common uni swap
wrapper and it makes more sense for everyone to use that or um yeah and especially for some of the tokens we need to make it really easy to make it very um like generic token uh Bridge just that we end up with just one token Bridge really or one canonical version says that we don't have 10 different versions for many of the D5 protocols it might not matter the same not if you using them as like saps so if they are stateless it doesn't matter that much if there's multiple of them if they have LP position stuff like that yeah you want it to just be one that is essentially used to to not make the the liquidity
super fragmented got it yep I hope it was not too confusing some of it was my question would be like are we going to have a different Shrine token like for example if it is going to have like this canonical portal made from us or is going to have a specific logic in the collab contract or something like that the Broner contract will never handle any funds so really everything but since you've been through these portals I think we will probably propose a way to
do token bridging um but we would prefer if it's not us that like actually deploy or set up any of these yes as a just like the nice thing is that we could build a way to do it where you are very close to trustlet or trustless or like fully trustless you only have the same assumptions as doing stuff inside the rollup and we could just set up a page where like okay this is how you can deploy it that's essentially what um arbitrome at least it's then anyone can go to like they have a website it deploys these things and so if there's a token that hey you want to have this token on L2
you can just go then do it yourself you don't need to like be super technical to figure it out um the thing we're moving more to to doing stuff like that hmm okay thanks and the registration of portals will be done the same way we did registration of bridges and as the connect that is like through the lock contract or uh we're still thinking exactly out the linking but if you remember from earlier Max in my slide you have this contrast leaves where you had the portal address then take the contract address only two um so we need to have some kind of
handshake uh when you're when you're linking them and you could be linking them when you're deploying ORNL to so you don't need anything to happen on the uh the roller contract like also you don't need the same issues we had with like gas um because the Roll Up is not performing the calls the roll-up is just inserting these messages and then someone else needs to perform the calls so you don't have this dark select or not dos Vector as we had in elastic connect your hand up sure um I guess that
continues on the uh point about the link between the L1 and L2 contractor what how how flexible is this relationship in terms of upgradability can a portal start pointing at a different L2 address or no if you want upgradability and not SBF design right now at least if you want upgrade ability you could essentially if you have an upgradable one contract upgradable L2 contract then you can just upgrade those the points are the same um the other thing is like if you want to do like full upgrades and you have immutable contract then it's essential
migration and then it's two new things um you could also have that your L1 portal contract is essentially just like a relayer it doesn't hold any logic um really but it's just like forwarding messages to some other contract you have on it once is that you can easily swap that out um okay so I guess a bigger question is what upgradeability looks like we've been L2 uh yeah like my showcase delegate calls or it wasn't the list earlier um so if you have delegate calls you can make proxies and then you can change the
logic um in yeah in doing your contracts SMG yeah then our upgrade would be similar to what's going on if when we upgrade as they connect by the address and all the storage stays the same but like the rules of the contract change is there any um information on how many uh messages we can we can cope with both on the L1 or the L2 site I presume it's Unlimited on L2 side but um like insert or like are you talking about how much we can move along um yeah both in terms of message size
plus total total cap yeah so like because the messages were very close to just being Dash and a little over it they cost uh is essentially constant there and nice thing is that when when you're inserting Formula One the insertion is pretty expensive but it's not the robot that performs that for um like incoming transactions so you need to flip like one bit um when you're consuming those so that could be pretty cheap uh it's a bit more expensive when we we need to like update a storage slot when we insert a message from l20121 um but it's still pretty cheap um so we are essentially that like 20K
and a bit for for inserting messages so you could have a high limits is that we are not like strictly saying what it is um but this it might must be up to the sequence so then to include how many acts you want to uh and it also changed a little if they if there's a lot of duplicate messages they will essentially land on the same storage lot just incrementing a counter so if there's a lot of like deposits 10 10 Eve to something um like incentive deposits to curve whatever um you could have a case where okay all
of these can almost be consumed for like 15K um but if there's a lot of very different messages okay we we need to like update a new storage slot every time and so it should be pretty cheap to move them across okay any other questions awesome thanks let's say