[Music]
hello thanks a lot for coming I'm very
happy to see so many of you here tonight
I know it's been a long day and this is
the last two talks so thanks for staying
here so my name is Peter I'm a pral
engineer at scroll and today I want to
tell you about a recent rollup
Improvement proposal that is called l1s
load
so let's start by talking about what is
A1 s
load essentially A1 s load is a
pre-compile that is deployed on l2s like
scroll and other l2s that you as a de
developer who deploys your dep on L2 can
use to read State directory from
L1 so if there's any solidity devs
around here this is how it looks so this
is the contract that you would Deploy on
L2 it's very simple you can just take
the L1 contract address you can provide
one two or up to five storage Keys you
encode it and then call this precompile
and then at the end you get the result
back that you can decode and use in your
application
logic uh what happens under the hood is
that the sequencer fetches this data for
you through adjacent RPC
request or it can even look uh as simple
as this if if you provide some higher
level libraries you you know just call
the ls load uh read onsite intent there
you can use the data in your L2 contract
now today today at the venue I passed
this door and I like this kind of as a
metaphor uh so Alan EST is essentially
about keeping the door to storage open
to your L2
dep before we go into the implementation
uh let me highlight some use cases that
we've discovered because we've been
running this through some hackathons in
the last few months uh one of my
favorites is this uh cross layer tornado
cach imagine that you can deposit some
tokens into the shielded set on L1 and
then you can withdraw L2 uh very simless
user
experience or imagine that you deploy
your D on an L2 that doesn't have enss
in this case you could just uh use i1 to
directly look up uh names from the
i1s another example is defi so you could
create uh a defi dep where you can
borrow on L2 d by directly using
collateral on L1 without bridging this
from L1 to
L2 and for account obstruction wallets
you might have heard about key stores
the idea is that you manage all your
keys on one chain let's say on i1 and
when you update your keys you add or
delete a key uh this update is
automatically propagated to all your
Wallets on all the
chains so this last example would look
like this uh in the L1 contract you
would most likely have some kind of a
mapping where you store the authorized
signers and on L2 it's very simple you
just calculate the storage slot that
you're interested in and then you can
call l1s load read bull the sequencer
fet is the data for you and you can
decide in your L2 wallet whether this
signer is authorized or not so a Lo
makes this very easy to implement and
also very easy to use as a as a
developer uh now that you have a general
understanding of what is a load and what
are some use cases let me talk about why
do I think we need to provide this in
the sequencer level and the way I think
about this is that this is uh uh service
that the sequencer provides to you
basically MPT proofs as a service uh
because this is all doable already
without relying on this pre-compile but
it's very complex as a developer first
of all relaying the state root
information from L1 to L2 in a very
fiable way is very complex and then for
any interaction on L2 providing this MPT
proof is costly and also complex to
develop so let's just do the sequencer
and the pro do the heavy lifting so that
you as the da developer can focus on the
cool application logic that you want to
develop there have some serious there
have been some alternative proposals to
Alan asot in the past few years uh two
that we know of our L1 call and remote
static call and these are more powerful
in a way so from your out to contract
you can directly call A View function on
L1 basically execute uh a full evm uh
function but these are in our experience
not very friendly to zare lab so uh the
proving is costly and also for instance
Scrolls execution environment for which
we have aover is slightly different from
L1 so if within that prover you would
need to implement another execution
environment for ethereum calls and that
makes this very hard to develop on
zaps on the other hand A1 asot has the
the issue that you know if you interact
with a contract and it's upgraded and
the storage slots change that might be a
challenge or that might be an issue so
this is something you need to consider
as a developer in that regard A1 call
would be more
powerful all right now let's let me show
you this is implemented in in our
reference implementation in the
sequencer there are two prerequisites
before we jump into the implementation
the first prerequisite is what I call
trustless block hash relay so the L2
Network scroll in this example needs to
have a notion of uh what is the latest
L1 block basically it needs to have a
view of the L1 chain including the state
rout because you need the state roots to
to verify these proofs uh some rollups
already support this uh the way Works uh
in our system although it's not launch
domain at yet is the sequencer
optimistically relays blocks from L1 to
L2 we verified that these indeed form a
chain of blocks and then when we
finalize this back on ethereum uh we
check that the sequencer relate the
correct data so if the sequencer tries
to cheat then it will be unable to
finalize this on Al one so this is
doable but this is one of the
prerequisites the other prerequisite is
that any L2 node including non sequencer
noes so Fuller nodes must connect to an
L1 node because as I mentioned this
precom call is translated into an RPC
query So currently not all rollups
inforce this uh you might just follow
the unsafe chain from the peer-to-peer
layer from the sequencer but if you want
to support l1s load then all nodes need
to connect to an i one
Noe given these prerequisites it's
actually quite simple the execution part
of the pre-combine is quite simple uh I
copied the example from our go ethereum
Fork so you would just need to extend
your evm implementation to add a new
pre-compile and what it does is first of
all it needs it needs to read the latest
layer one block that we know of in our
case this is stored in States but this
might be implemented in other ways then
it needs to parse the inputs that the
developer provided uh execute a batch
RPC call so even if you read five
storage slots the latency is the same
because we can batch these queries and
then resume execution and return control
to the evm
execution so that was the execution and
on the verification side as mentioned we
need to verify uh the block hash relay
so verify the L1 header chain and verify
that the sequencer relay the correct
information and then as part of the
proving process the sequencer also
fetches these MPT proofs uh so that you
as the developer don't need to do that
and inside approver we need to verify
all these lay one MPT proofs and make
sure that these were all
correct now we have this rollup
Improvement proposal but this is still a
draft and there are still some open
questions
and the main goal of this talk is to
involve more people so if you're a
developer who might be interested in
using this then we love to hear for hear
from you see what you need uh and if you
are an L2 protocol maintainer you know
you're maintaining a sequencer note then
you're interested in adopting this then
we'd also love to hear from you to share
your
input so I want to highlight three open
questions uh one open question that we
received from devs actually is that like
do we want to allow L2 applications to
read A1 State at arbitrary height so not
just the latest A1 height but maybe
older State definitely for some
applications this is
required but this also has some
drawbacks for instance if you allow
reading Old State then the nodes must
connect to an archive at one note and
for some L1 nodes like WTH I believe
this is not even possible because it
cannot serve historical uh G proof
requests another question is how do you
deal with RPC errors and latency when
you execute uh these calls to the L1 SL
load pre-compile latency is a big
question mark to me because if there's a
latency between the L2 node and the L1
node you know the RPC query that might
affect the throughput of the system that
might slow your system down so you need
to consider that when you price this
pre-compile and if you encounter an
error you need to decide do I retry or
do I drop this
transaction and finally defining the gas
cost is also tricky so in our proposal
we have a very simple pricing mechanism
basically a fixed cost per pre-c compi
call and variable cost um or another
fixed cost per the number of slots that
you're quarrying but this is not all you
also have to pay for producing and
verifying these MPT proofs uh that is
probably you can do some benchmarking to
price that and what's kind of tricky is
to price this RPC latency like what is
the cost of doing this RPC query on the
sequencer as opposed to processing other
transactions
so we still have some way to go this rip
was proposed in June and uh it's now
gaining some traction we've been
exploring some use cases but the next
step would be to involve more uh L2 dep
developers and L2 protol teams so as I
mentioned we'd love to hear from you uh
just recently we set up a working group
telegram channel so if you're interested
in joining the discussion feel free to
join if you cannot join for some reason
then feel free to message me on Twitter
and I add you
and I really hope that we get support
from at least one other L2 team and that
we can ship this feature on at least two
l2s maybe in
2025 and in this presentation I also
have some resources both uh the
reference implementation The eth
Magicians link and we also have some uh
resources for devs uh devnet and some
example codes that you can use to get
some
inspiration that's all I have for today
and I'm looking forward to your
questions thank you
thank you Peter we have a few questions
so first question is what happens when I
load a state from L1 but then L1
reorgs yeah that's a good question so
the question is uh when does the
sequencer relay this if the sequencer is
conservative and it weighs for L1 to
finalize then this won't happen but then
the user experience is not very good
because the latency is uh 12 to 15
minutes if the sequencer uh relays it
earlier maybe after a couple of minutes
then us ASD L2 need to be reorg aware so
you need to detect reorgs and you need
to reor along uh with the one most
likely but I think this is the same
problem that l2s have with uh deposits
so any information that relate from L1
to L2 be it L1 s load or deposit
transactions have the same
issue okay NE next question is what is
the latency of data relay from ethereum
to L2
yeah so that's essentially it boyss down
to the same question like if you want to
be conservative just wait for
finalization if not you need to reor
along with L1 um in reality it's not
terrible because I think L1 hasn't had a
reor deeper than seven slots or is
extremely unlikely so as long as you
have a mechanism to reor if there's a
deeper RoR then this won't really be
triggered in most scenarios but there's
still the issue on one of the Ina
activity leak what if L1 doesn't
finalize for a long time in this case
definitely being more aggressive and not
waiting for finalization would be the
way to go otherwise user experience
would
suffer okay next question is why is it
only limited to five
Keys yeah that's a good question do you
need more than five keys if yes then
please let us know five is was just an
arbitrary number we didn't want to make
it unbounded uh for most application use
cases that we explor
five or less was enough but if you think
it's not enough then uh this is still
draft so we can still change
it okay uh which state or block does
this op code load form uh is it the
latest ethereum
block it is the latest ethereum block
that this L2 blockchain knows of so um
there needs to be on this L2 Network it
has multiple notes sequencer and follow
notes they need to have a consensus
about what is the latest l one block
that they see otherwise uh execution to
cuse to this pre compile would diverge
but this could be implemented in
different ways I mentioned this as uh
one of the prerequisites and I would say
this is not in the scope uh of this Rip
but it's a prerequisite that could be
implemented in different ways for
different
rollups okay uh what happens if there is
a small reorg for the specific L1 node
at the tip then the L2 sequencer would
process incorrect data to to the L2 how
would execution continue on the
L2 yeah same question as before so you
would need to most likely reor along
with that
one okay how do you configure switching
the RPC node on a live e
sequencer how do you configure
switching well I mean you can get fancy
I mean the easiest solution is to just
compare connect to one node but
obviously that's not robust what if the
node is down so ideally you would set up
multip L1 RPC nodes U ideally multiple
types of L1 clients and then have a load
balancer and then you can dynamically
switch off and add nodes uh that's
robust for the sequencer and for L2
nodes probably it's enough to just uh
run a sing Single a one
Noe okay um is this the same as the
previous questions or is this separate
question when I load L1 stage should I
specify L1 block number it's a different
question in the current version of the
spec you cannot specify an A1 number in
a previous version you could so as I
mentioned this is one of the open
questions and I guess we need to learn
more for from developers to decide which
way to
go okay uh when will will when will s L1
s load be available on mainnet soon I
hope so but this is not very useful if
only one rollup ships it so I hope at
least two rollups can ship it next year
somebody want wants to know what is
RP so rip stands for rollup Improvement
proposal this is similar to the EIP
process that is for L1 and we have a
less binding kind of collaborative
process for L2 that is called RP oh
times up um thank you and if anybody has
any more questions uh please find him uh
by the stage thank you thank you